From a9fa6548a0a376774407fe4d025e12487a700c42 Mon Sep 17 00:00:00 2001 From: JoJoJet Date: Tue, 7 Jun 2022 03:52:41 -0400 Subject: [PATCH 01/12] use a simpler design for *Label Rewrite {System,Stage,*}Label to use a simpler design. *Label is now a lightweight, copy-able struct. You derive `Into*Label` on your custom labels. --- crates/bevy_ecs/macros/src/lib.rs | 18 ++++---- crates/bevy_ecs/src/schedule/label.rs | 17 +++----- crates/bevy_macro_utils/src/lib.rs | 35 +++++++++++++-- crates/bevy_utils/src/label.rs | 63 +++++++++++++++------------ 4 files changed, 84 insertions(+), 49 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 5722872df15e2..79eb18a3176bd 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -434,45 +434,47 @@ pub fn derive_world_query(input: TokenStream) -> TokenStream { derive_world_query_impl(ast) } -#[proc_macro_derive(SystemLabel)] +#[proc_macro_derive(IntoSystemLabel)] pub fn derive_system_label(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let mut trait_path = bevy_ecs_path(); trait_path.segments.push(format_ident!("schedule").into()); trait_path .segments - .push(format_ident!("SystemLabel").into()); + .push(format_ident!("IntoSystemLabel").into()); derive_label(input, &trait_path) } -#[proc_macro_derive(StageLabel)] +#[proc_macro_derive(IntoStageLabel)] pub fn derive_stage_label(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let mut trait_path = bevy_ecs_path(); trait_path.segments.push(format_ident!("schedule").into()); - trait_path.segments.push(format_ident!("StageLabel").into()); + trait_path + .segments + .push(format_ident!("IntoStageLabel").into()); derive_label(input, &trait_path) } -#[proc_macro_derive(AmbiguitySetLabel)] +#[proc_macro_derive(IntoAmbiguitySetLabel)] pub fn derive_ambiguity_set_label(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let mut trait_path = bevy_ecs_path(); trait_path.segments.push(format_ident!("schedule").into()); trait_path .segments - .push(format_ident!("AmbiguitySetLabel").into()); + .push(format_ident!("IntoAmbiguitySetLabel").into()); derive_label(input, &trait_path) } -#[proc_macro_derive(RunCriteriaLabel)] +#[proc_macro_derive(IntoRunCriteriaLabel)] pub fn derive_run_criteria_label(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let mut trait_path = bevy_ecs_path(); trait_path.segments.push(format_ident!("schedule").into()); trait_path .segments - .push(format_ident!("RunCriteriaLabel").into()); + .push(format_ident!("IntoRunCriteriaLabel").into()); derive_label(input, &trait_path) } diff --git a/crates/bevy_ecs/src/schedule/label.rs b/crates/bevy_ecs/src/schedule/label.rs index 5235dc5837692..2f87ec5752062 100644 --- a/crates/bevy_ecs/src/schedule/label.rs +++ b/crates/bevy_ecs/src/schedule/label.rs @@ -1,12 +1,9 @@ -pub use bevy_ecs_macros::{AmbiguitySetLabel, RunCriteriaLabel, StageLabel, SystemLabel}; +pub use bevy_ecs_macros::{ + IntoAmbiguitySetLabel, IntoRunCriteriaLabel, IntoStageLabel, IntoSystemLabel, +}; use bevy_utils::define_label; -define_label!(StageLabel); -define_label!(SystemLabel); -define_label!(AmbiguitySetLabel); -define_label!(RunCriteriaLabel); - -pub(crate) type BoxedStageLabel = Box; -pub(crate) type BoxedSystemLabel = Box; -pub(crate) type BoxedAmbiguitySetLabel = Box; -pub(crate) type BoxedRunCriteriaLabel = Box; +define_label!(StageLabel, IntoStageLabel); +define_label!(SystemLabel, IntoSystemLabel); +define_label!(AmbiguitySetLabel, IntoAmbiguitySetLabel); +define_label!(RunCriteriaLabel, IntoRunCriteriaLabel); diff --git a/crates/bevy_macro_utils/src/lib.rs b/crates/bevy_macro_utils/src/lib.rs index d1ab5cc40f60f..453e86cb4e6b2 100644 --- a/crates/bevy_macro_utils/src/lib.rs +++ b/crates/bevy_macro_utils/src/lib.rs @@ -118,12 +118,41 @@ pub fn derive_label(input: syn::DeriveInput, trait_path: &syn::Path) -> TokenStr where_token: Default::default(), predicates: Default::default(), }); - where_clause.predicates.push(syn::parse2(quote! { Self: Eq + ::std::fmt::Debug + ::std::hash::Hash + Clone + Send + Sync + 'static }).unwrap()); + where_clause + .predicates + .push(syn::parse2(quote! { Self: 'static }).unwrap()); + + let as_str = match input.data { + syn::Data::Struct(d) => match d.fields { + syn::Fields::Unit => { + let lit = ident.to_string(); + quote! { #lit } + } + _ => panic!("only unit structs can be Labels"), + }, + syn::Data::Enum(d) => { + let arms = d.variants.iter().map(|v| match v.fields { + syn::Fields::Unit => { + let mut path = syn::Path::from(ident.clone()); + path.segments.push(v.ident.clone().into()); + let lit = format!("{ident}::{}", v.ident.clone()); + quote! { #path => #lit } + } + _ => panic!("only unit variants can be Labels"), + }); + quote! { + match self { + #(#arms),* + } + } + } + syn::Data::Union(_) => panic!("unions are not supported"), + }; (quote! { impl #impl_generics #trait_path for #ident #ty_generics #where_clause { - fn dyn_clone(&self) -> std::boxed::Box { - std::boxed::Box::new(std::clone::Clone::clone(self)) + fn as_str(&self) -> &'static str { + #as_str } } }) diff --git a/crates/bevy_utils/src/label.rs b/crates/bevy_utils/src/label.rs index e161aa5fbe935..07e86291c8aa2 100644 --- a/crates/bevy_utils/src/label.rs +++ b/crates/bevy_utils/src/label.rs @@ -57,44 +57,51 @@ where /// ``` #[macro_export] macro_rules! define_label { - ($label_trait_name:ident) => { - /// Defines a set of strongly-typed labels for a class of objects - pub trait $label_trait_name: - $crate::label::DynHash + ::std::fmt::Debug + Send + Sync + 'static - { - #[doc(hidden)] - fn dyn_clone(&self) -> Box; - } - - impl PartialEq for dyn $label_trait_name { - fn eq(&self, other: &Self) -> bool { - self.dyn_eq(other.as_dyn_eq()) + ($label_type_name:ident, $as_label:ident) => { + /// Stores one of a set of strongly-typed labels for a class of objects. + #[derive(Clone, Copy, PartialEq, Eq, Hash)] + pub struct $label_type_name(::core::any::TypeId, &'static str); + + impl ::core::fmt::Debug for $label_type_name { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}", self.1) } } - impl Eq for dyn $label_trait_name {} - - impl ::std::hash::Hash for dyn $label_trait_name { - fn hash(&self, state: &mut H) { - self.dyn_hash(state); + /// Types that can be coerced into [`$label_type_name`]. + pub trait $as_label: 'static { + /// Converts this type into an opaque, strongly-typed label. + fn as_label(&self) -> $label_type_name { + let id = self.type_id(); + let label = self.as_str(); + $label_type_name(id, label) } - } - - impl Clone for Box { - fn clone(&self) -> Self { - self.dyn_clone() + /// Returns the [`TypeId`] used to differentiate labels. + fn type_id(&self) -> ::core::any::TypeId { + ::core::any::TypeId::of::() } + /// Returns the representation of this label as a string literal. + /// + /// In cases where you absolutely need a label to be determined at runtime, + /// you can use [`Box::leak`] to get a `'static` reference. + fn as_str(&self) -> &'static str; } - impl $label_trait_name for ::std::borrow::Cow<'static, str> { - fn dyn_clone(&self) -> Box { - Box::new(self.clone()) + impl $as_label for $label_type_name { + fn as_label(&self) -> Self { + *self + } + fn type_id(&self) -> ::core::any::TypeId { + self.0 + } + fn as_str(&self) -> &'static str { + self.1 } } - impl $label_trait_name for &'static str { - fn dyn_clone(&self) -> Box { - Box::new(<&str>::clone(self)) + impl $as_label for &'static str { + fn as_str(&self) -> Self { + self } } }; From fecd6978460b77758c5a7c0218966516e13cbbae Mon Sep 17 00:00:00 2001 From: JoJoJet Date: Tue, 7 Jun 2022 03:54:04 -0400 Subject: [PATCH 02/12] Update the workspace to use the new Label API Update lib.rs Update lib.rs --- crates/bevy_app/src/app.rs | 67 ++++---- crates/bevy_app/src/lib.rs | 8 +- crates/bevy_asset/src/asset_server.rs | 2 +- crates/bevy_asset/src/lib.rs | 6 +- crates/bevy_derive/src/lib.rs | 6 +- crates/bevy_ecs/examples/change_detection.rs | 4 +- crates/bevy_ecs/src/lib.rs | 8 +- crates/bevy_ecs/src/schedule/mod.rs | 77 +++++---- crates/bevy_ecs/src/schedule/run_criteria.rs | 79 ++++----- crates/bevy_ecs/src/schedule/stage.rs | 160 +++++++++--------- crates/bevy_ecs/src/schedule/state.rs | 21 ++- .../bevy_ecs/src/schedule/system_container.rs | 54 +++--- .../src/schedule/system_descriptor.rs | 76 ++++----- crates/bevy_ecs/src/schedule/system_set.rs | 25 ++- crates/bevy_ecs/src/system/function_system.rs | 16 +- crates/bevy_ecs/src/system/system.rs | 2 +- crates/bevy_hierarchy/src/lib.rs | 8 + crates/bevy_input/src/lib.rs | 4 +- crates/bevy_pbr/src/light.rs | 2 +- crates/bevy_pbr/src/render/light.rs | 2 +- crates/bevy_render/src/camera/projection.rs | 2 +- crates/bevy_render/src/lib.rs | 6 +- crates/bevy_render/src/render_asset.rs | 2 +- crates/bevy_render/src/view/visibility/mod.rs | 2 +- crates/bevy_render/src/view/window.rs | 2 +- crates/bevy_sprite/src/lib.rs | 4 +- crates/bevy_time/src/lib.rs | 4 +- crates/bevy_transform/src/lib.rs | 4 +- crates/bevy_ui/src/lib.rs | 4 +- crates/bevy_ui/src/render/mod.rs | 2 +- crates/bevy_utils/src/label.rs | 2 +- crates/bevy_window/src/lib.rs | 4 +- examples/ecs/ecs_guide.rs | 2 +- examples/ecs/fixed_timestep.rs | 2 +- examples/ecs/iter_combinations.rs | 2 +- examples/ecs/system_sets.rs | 4 +- examples/tools/scene_viewer.rs | 2 +- 37 files changed, 349 insertions(+), 328 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 4d72c15e7d4ed..557e61195dbc3 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1,11 +1,11 @@ use crate::{CoreStage, Plugin, PluginGroup, PluginGroupBuilder, StartupSchedule, StartupStage}; -pub use bevy_derive::AppLabel; +pub use bevy_derive::IntoAppLabel; use bevy_ecs::{ event::{Event, Events}, prelude::{FromWorld, IntoExclusiveSystem}, schedule::{ - IntoSystemDescriptor, Schedule, ShouldRun, Stage, StageLabel, State, StateData, SystemSet, - SystemStage, + IntoStageLabel, IntoSystemDescriptor, Schedule, ShouldRun, Stage, State, StateData, + SystemSet, SystemStage, }, system::Resource, world::World, @@ -15,7 +15,7 @@ use std::fmt::Debug; #[cfg(feature = "trace")] use bevy_utils::tracing::info_span; -bevy_utils::define_label!(AppLabel); +bevy_utils::define_label!(AppLabel, IntoAppLabel); #[allow(clippy::needless_doctest_main)] /// A container of app logic and data. @@ -56,7 +56,7 @@ pub struct App { pub runner: Box, /// A container of [`Stage`]s set to be run in a linear order. pub schedule: Schedule, - sub_apps: HashMap, SubApp>, + sub_apps: HashMap, } /// Each `SubApp` has its own [`Schedule`] and [`World`], enabling a separation of concerns. @@ -142,7 +142,7 @@ impl App { /// # /// app.add_stage("my_stage", SystemStage::parallel()); /// ``` - pub fn add_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { + pub fn add_stage(&mut self, label: impl IntoStageLabel, stage: S) -> &mut Self { self.schedule.add_stage(label, stage); self } @@ -161,8 +161,8 @@ impl App { /// ``` pub fn add_stage_after( &mut self, - target: impl StageLabel, - label: impl StageLabel, + target: impl IntoStageLabel, + label: impl IntoStageLabel, stage: S, ) -> &mut Self { self.schedule.add_stage_after(target, label, stage); @@ -183,8 +183,8 @@ impl App { /// ``` pub fn add_stage_before( &mut self, - target: impl StageLabel, - label: impl StageLabel, + target: impl IntoStageLabel, + label: impl IntoStageLabel, stage: S, ) -> &mut Self { self.schedule.add_stage_before(target, label, stage); @@ -203,7 +203,11 @@ impl App { /// # /// app.add_startup_stage("my_startup_stage", SystemStage::parallel()); /// ``` - pub fn add_startup_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { + pub fn add_startup_stage( + &mut self, + label: impl IntoStageLabel, + stage: S, + ) -> &mut Self { self.schedule .stage(StartupSchedule, |schedule: &mut Schedule| { schedule.add_stage(label, stage) @@ -231,8 +235,8 @@ impl App { /// ``` pub fn add_startup_stage_after( &mut self, - target: impl StageLabel, - label: impl StageLabel, + target: impl IntoStageLabel, + label: impl IntoStageLabel, stage: S, ) -> &mut Self { self.schedule @@ -262,8 +266,8 @@ impl App { /// ``` pub fn add_startup_stage_before( &mut self, - target: impl StageLabel, - label: impl StageLabel, + target: impl IntoStageLabel, + label: impl IntoStageLabel, stage: S, ) -> &mut Self { self.schedule @@ -299,7 +303,7 @@ impl App { /// ``` pub fn stage &mut T>( &mut self, - label: impl StageLabel, + label: impl IntoStageLabel, func: F, ) -> &mut Self { self.schedule.stage(label, func); @@ -365,7 +369,7 @@ impl App { /// ``` pub fn add_system_to_stage( &mut self, - stage_label: impl StageLabel, + stage_label: impl IntoStageLabel, system: impl IntoSystemDescriptor, ) -> &mut Self { use std::any::TypeId; @@ -400,7 +404,7 @@ impl App { /// ``` pub fn add_system_set_to_stage( &mut self, - stage_label: impl StageLabel, + stage_label: impl IntoStageLabel, system_set: SystemSet, ) -> &mut Self { use std::any::TypeId; @@ -480,7 +484,7 @@ impl App { /// ``` pub fn add_startup_system_to_stage( &mut self, - stage_label: impl StageLabel, + stage_label: impl IntoStageLabel, system: impl IntoSystemDescriptor, ) -> &mut Self { self.schedule @@ -516,7 +520,7 @@ impl App { /// ``` pub fn add_startup_system_set_to_stage( &mut self, - stage_label: impl StageLabel, + stage_label: impl IntoStageLabel, system_set: SystemSet, ) -> &mut Self { self.schedule @@ -543,7 +547,7 @@ impl App { /// Each stage that uses `State` for system run criteria needs a driver. If you need to use /// your state in more than one stage, consider manually adding [`State::get_driver`] to the /// stages you need it in. - pub fn add_state_to_stage(&mut self, stage: impl StageLabel, initial: T) -> &mut Self + pub fn add_state_to_stage(&mut self, stage: impl IntoStageLabel, initial: T) -> &mut Self where T: StateData, { @@ -874,12 +878,12 @@ impl App { /// reference to the `SubApp` itself. pub fn add_sub_app( &mut self, - label: impl AppLabel, + label: impl IntoAppLabel, app: App, sub_app_runner: impl Fn(&mut World, &mut App) + 'static, ) -> &mut Self { self.sub_apps.insert( - Box::new(label), + label.as_label(), SubApp { app, runner: Box::new(sub_app_runner), @@ -893,18 +897,19 @@ impl App { /// # Panics /// /// Panics if the `SubApp` doesn't exist. - pub fn sub_app_mut(&mut self, label: impl AppLabel) -> &mut App { + pub fn sub_app_mut(&mut self, label: impl IntoAppLabel) -> &mut App { match self.get_sub_app_mut(label) { Ok(app) => app, - Err(label) => panic!("Sub-App with label '{:?}' does not exist", label), + Err(label) => panic!("Sub-App with label '{:?}' does not exist", label.as_str()), } } /// Retrieves a `SubApp` inside this [`App`] with the given label, if it exists. Otherwise returns /// an [`Err`] containing the given label. - pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Result<&mut App, impl AppLabel> { + pub fn get_sub_app_mut(&mut self, label: impl IntoAppLabel) -> Result<&mut App, AppLabel> { + let label = label.as_label(); self.sub_apps - .get_mut((&label) as &dyn AppLabel) + .get_mut(&label) .map(|sub_app| &mut sub_app.app) .ok_or(label) } @@ -914,18 +919,18 @@ impl App { /// # Panics /// /// Panics if the `SubApp` doesn't exist. - pub fn sub_app(&self, label: impl AppLabel) -> &App { + pub fn sub_app(&self, label: impl IntoAppLabel) -> &App { match self.get_sub_app(label) { Ok(app) => app, - Err(label) => panic!("Sub-App with label '{:?}' does not exist", label), + Err(label) => panic!("Sub-App with label '{:?}' does not exist", label.as_str()), } } /// Retrieves a `SubApp` inside this [`App`] with the given label, if it exists. Otherwise returns /// an [`Err`] containing the given label. - pub fn get_sub_app(&self, label: impl AppLabel) -> Result<&App, impl AppLabel> { + pub fn get_sub_app(&self, label: impl IntoAppLabel) -> Result<&App, impl IntoAppLabel> { self.sub_apps - .get((&label) as &dyn AppLabel) + .get(&label.as_label()) .map(|sub_app| &sub_app.app) .ok_or(label) } diff --git a/crates/bevy_app/src/lib.rs b/crates/bevy_app/src/lib.rs index c0a9c68f79c3f..cf203f13715e7 100644 --- a/crates/bevy_app/src/lib.rs +++ b/crates/bevy_app/src/lib.rs @@ -24,12 +24,12 @@ pub mod prelude { }; } -use bevy_ecs::schedule::StageLabel; +use bevy_ecs::schedule::IntoStageLabel; /// The names of the default [`App`] stages. /// /// The relative [`Stages`](bevy_ecs::schedule::Stage) are added by [`App::add_default_stages`]. -#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] +#[derive(Debug, Hash, PartialEq, Eq, Clone, IntoStageLabel)] pub enum CoreStage { /// The [`Stage`](bevy_ecs::schedule::Stage) that runs before all other app stages. First, @@ -48,11 +48,11 @@ pub enum CoreStage { /// /// When targeting a [`Stage`](bevy_ecs::schedule::Stage) inside this [`Schedule`](bevy_ecs::schedule::Schedule), /// you need to use [`StartupStage`] instead. -#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] +#[derive(Debug, Hash, PartialEq, Eq, Clone, IntoStageLabel)] pub struct StartupSchedule; /// The names of the default [`App`] startup stages. -#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] +#[derive(Debug, Hash, PartialEq, Eq, Clone, IntoStageLabel)] pub enum StartupStage { /// The [`Stage`](bevy_ecs::schedule::Stage) that runs once before [`StartupStage::Startup`]. PreStartup, diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 249d7c0f6f437..5ca554aff18fa 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -848,7 +848,7 @@ mod test { asset_server.add_loader(FakePngLoader); let assets = asset_server.register_asset_type::(); - #[derive(SystemLabel, Clone, Hash, Debug, PartialEq, Eq)] + #[derive(IntoSystemLabel, Clone, Hash, Debug, PartialEq, Eq)] struct FreeUnusedAssets; let mut app = App::new(); app.insert_resource(assets); diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index f70bc5c1f4fd4..c047d1a3cd4f2 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -42,10 +42,10 @@ pub use loader::*; pub use path::*; use bevy_app::{prelude::Plugin, App}; -use bevy_ecs::schedule::{StageLabel, SystemStage}; +use bevy_ecs::schedule::{IntoStageLabel, SystemStage}; -/// The names of asset stages in an [`App`] schedule. -#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] +/// The names of asset stages in an App Schedule +#[derive(Debug, Hash, PartialEq, Eq, Clone, IntoStageLabel)] pub enum AssetStage { /// The stage where asset storages are updated. LoadAssets, diff --git a/crates/bevy_derive/src/lib.rs b/crates/bevy_derive/src/lib.rs index 3c43776ef9961..ddd923269b24b 100644 --- a/crates/bevy_derive/src/lib.rs +++ b/crates/bevy_derive/src/lib.rs @@ -80,10 +80,12 @@ pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream { enum_variant_meta::derive_enum_variant_meta(input) } -#[proc_macro_derive(AppLabel)] +#[proc_macro_derive(IntoAppLabel)] pub fn derive_app_label(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as syn::DeriveInput); let mut trait_path = BevyManifest::default().get_path("bevy_app"); - trait_path.segments.push(format_ident!("AppLabel").into()); + trait_path + .segments + .push(format_ident!("IntoAppLabel").into()); derive_label(input, &trait_path) } diff --git a/crates/bevy_ecs/examples/change_detection.rs b/crates/bevy_ecs/examples/change_detection.rs index 8477a5164f44a..89a03f54de813 100644 --- a/crates/bevy_ecs/examples/change_detection.rs +++ b/crates/bevy_ecs/examples/change_detection.rs @@ -1,4 +1,4 @@ -use bevy_ecs::prelude::*; +use bevy_ecs::{prelude::*, schedule::IntoSystemLabel}; use rand::Rng; use std::ops::Deref; @@ -52,7 +52,7 @@ struct Age { } // System labels to enforce a run order of our systems -#[derive(SystemLabel, Debug, Clone, PartialEq, Eq, Hash)] +#[derive(IntoSystemLabel, Debug, Clone, PartialEq, Eq, Hash)] enum SimulationSystem { Spawn, Age, diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index cafacc2a2d929..c2cb2321a0b08 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -34,9 +34,11 @@ pub mod prelude { event::{EventReader, EventWriter, Events}, query::{Added, AnyOf, ChangeTrackers, Changed, Or, QueryState, With, Without}, schedule::{ - AmbiguitySetLabel, ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion, - RunCriteria, RunCriteriaDescriptorCoercion, RunCriteriaLabel, Schedule, Stage, - StageLabel, State, SystemLabel, SystemSet, SystemStage, + AmbiguitySetLabel, ExclusiveSystemDescriptorCoercion, IntoAmbiguitySetLabel, + IntoRunCriteriaLabel, IntoStageLabel, IntoSystemLabel, + ParallelSystemDescriptorCoercion, RunCriteria, RunCriteriaDescriptorCoercion, + RunCriteriaLabel, Schedule, Stage, StageLabel, State, SystemLabel, SystemSet, + SystemStage, }, system::{ Commands, In, IntoChainSystem, IntoExclusiveSystem, IntoSystem, Local, NonSend, diff --git a/crates/bevy_ecs/src/schedule/mod.rs b/crates/bevy_ecs/src/schedule/mod.rs index 1aab0f0f4414d..14ff543820508 100644 --- a/crates/bevy_ecs/src/schedule/mod.rs +++ b/crates/bevy_ecs/src/schedule/mod.rs @@ -38,15 +38,15 @@ use bevy_utils::HashMap; /// runs indefinitely. #[derive(Default)] pub struct Schedule { - stages: HashMap>, - stage_order: Vec, + stages: HashMap>, + stage_order: Vec, run_criteria: BoxedRunCriteria, } impl Schedule { /// Similar to [`add_stage`](Self::add_stage), but it also returns itself. #[must_use] - pub fn with_stage(mut self, label: impl StageLabel, stage: S) -> Self { + pub fn with_stage(mut self, label: impl IntoStageLabel, stage: S) -> Self { self.add_stage(label, stage); self } @@ -55,8 +55,8 @@ impl Schedule { #[must_use] pub fn with_stage_after( mut self, - target: impl StageLabel, - label: impl StageLabel, + target: impl IntoStageLabel, + label: impl IntoStageLabel, stage: S, ) -> Self { self.add_stage_after(target, label, stage); @@ -67,8 +67,8 @@ impl Schedule { #[must_use] pub fn with_stage_before( mut self, - target: impl StageLabel, - label: impl StageLabel, + target: impl IntoStageLabel, + label: impl IntoStageLabel, stage: S, ) -> Self { self.add_stage_before(target, label, stage); @@ -85,7 +85,7 @@ impl Schedule { #[must_use] pub fn with_system_in_stage( mut self, - stage_label: impl StageLabel, + stage_label: impl IntoStageLabel, system: impl IntoSystemDescriptor, ) -> Self { self.add_system_to_stage(stage_label, system); @@ -108,10 +108,10 @@ impl Schedule { /// # let mut schedule = Schedule::default(); /// schedule.add_stage("my_stage", SystemStage::parallel()); /// ``` - pub fn add_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { - let label: Box = Box::new(label); - self.stage_order.push(label.clone()); - let prev = self.stages.insert(label.clone(), Box::new(stage)); + pub fn add_stage(&mut self, label: impl IntoStageLabel, stage: S) -> &mut Self { + let label = label.as_label(); + self.stage_order.push(label); + let prev = self.stages.insert(label, Box::new(stage)); assert!(prev.is_none(), "Stage already exists: {:?}.", label); self } @@ -129,22 +129,22 @@ impl Schedule { /// ``` pub fn add_stage_after( &mut self, - target: impl StageLabel, - label: impl StageLabel, + target: impl IntoStageLabel, + label: impl IntoStageLabel, stage: S, ) -> &mut Self { - let label: Box = Box::new(label); - let target = &target as &dyn StageLabel; + let label = label.as_label(); + let target = target.as_label(); let target_index = self .stage_order .iter() .enumerate() - .find(|(_i, stage_label)| &***stage_label == target) + .find(|(_i, stage_label)| **stage_label == target) .map(|(i, _)| i) .unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target)); - self.stage_order.insert(target_index + 1, label.clone()); - let prev = self.stages.insert(label.clone(), Box::new(stage)); + self.stage_order.insert(target_index + 1, label); + let prev = self.stages.insert(label, Box::new(stage)); assert!(prev.is_none(), "Stage already exists: {:?}.", label); self } @@ -163,22 +163,22 @@ impl Schedule { /// ``` pub fn add_stage_before( &mut self, - target: impl StageLabel, - label: impl StageLabel, + target: impl IntoStageLabel, + label: impl IntoStageLabel, stage: S, ) -> &mut Self { - let label: Box = Box::new(label); - let target = &target as &dyn StageLabel; + let label = label.as_label(); + let target = target.as_label(); let target_index = self .stage_order .iter() .enumerate() - .find(|(_i, stage_label)| &***stage_label == target) + .find(|(_i, stage_label)| **stage_label == target) .map(|(i, _)| i) .unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target)); - self.stage_order.insert(target_index, label.clone()); - let prev = self.stages.insert(label.clone(), Box::new(stage)); + self.stage_order.insert(target_index, label); + let prev = self.stages.insert(label, Box::new(stage)); assert!(prev.is_none(), "Stage already exists: {:?}.", label); self } @@ -198,7 +198,7 @@ impl Schedule { /// ``` pub fn add_system_to_stage( &mut self, - stage_label: impl StageLabel, + stage_label: impl IntoStageLabel, system: impl IntoSystemDescriptor, ) -> &mut Self { // Use a function instead of a closure to ensure that it is codegend inside bevy_ecs instead @@ -213,7 +213,7 @@ impl Schedule { let stage = self .get_stage_mut::(&stage_label) - .unwrap_or_else(move || stage_not_found(&stage_label)); + .unwrap_or_else(move || stage_not_found(&stage_label.as_label())); stage.add_system(system); self } @@ -243,7 +243,7 @@ impl Schedule { /// ``` pub fn add_system_set_to_stage( &mut self, - stage_label: impl StageLabel, + stage_label: impl IntoStageLabel, system_set: SystemSet, ) -> &mut Self { self.stage(stage_label, |stage: &mut SystemStage| { @@ -278,11 +278,14 @@ impl Schedule { /// Panics if `label` refers to a non-existing stage, or if it's not of type `T`. pub fn stage &mut T>( &mut self, - label: impl StageLabel, + label: impl IntoStageLabel, func: F, ) -> &mut Self { let stage = self.get_stage_mut::(&label).unwrap_or_else(move || { - panic!("stage '{:?}' does not exist or is the wrong type", label) + panic!( + "stage '{:?}' does not exist or is the wrong type", + label.as_label() + ) }); func(stage); self @@ -303,9 +306,9 @@ impl Schedule { /// # /// let stage = schedule.get_stage::(&"my_stage").unwrap(); /// ``` - pub fn get_stage(&self, label: &dyn StageLabel) -> Option<&T> { + pub fn get_stage(&self, label: &dyn IntoStageLabel) -> Option<&T> { self.stages - .get(label) + .get(&label.as_label()) .and_then(|stage| stage.downcast_ref::()) } @@ -324,9 +327,9 @@ impl Schedule { /// # /// let stage = schedule.get_stage_mut::(&"my_stage").unwrap(); /// ``` - pub fn get_stage_mut(&mut self, label: &dyn StageLabel) -> Option<&mut T> { + pub fn get_stage_mut(&mut self, label: &dyn IntoStageLabel) -> Option<&mut T> { self.stages - .get_mut(label) + .get_mut(&label.as_label()) .and_then(|stage| stage.downcast_mut::()) } @@ -341,10 +344,10 @@ impl Schedule { } /// Iterates over all of schedule's stages and their labels, in execution order. - pub fn iter_stages(&self) -> impl Iterator { + pub fn iter_stages(&self) -> impl Iterator { self.stage_order .iter() - .map(move |label| (&**label, &*self.stages[label])) + .map(move |&label| (label, &*self.stages[&label])) } } diff --git a/crates/bevy_ecs/src/schedule/run_criteria.rs b/crates/bevy_ecs/src/schedule/run_criteria.rs index 6bc7320c357a0..ded86f83a8854 100644 --- a/crates/bevy_ecs/src/schedule/run_criteria.rs +++ b/crates/bevy_ecs/src/schedule/run_criteria.rs @@ -1,5 +1,5 @@ use crate::{ - schedule::{BoxedRunCriteriaLabel, GraphNode, RunCriteriaLabel}, + schedule::{GraphNode, IntoRunCriteriaLabel, RunCriteriaLabel}, system::{BoxedSystem, IntoSystem, Local}, world::World, }; @@ -94,9 +94,9 @@ pub(crate) enum RunCriteriaInner { pub(crate) struct RunCriteriaContainer { pub(crate) should_run: ShouldRun, pub(crate) inner: RunCriteriaInner, - pub(crate) label: Option, - pub(crate) before: Vec, - pub(crate) after: Vec, + pub(crate) label: Option, + pub(crate) before: Vec, + pub(crate) after: Vec, } impl RunCriteriaContainer { @@ -129,7 +129,7 @@ impl RunCriteriaContainer { } impl GraphNode for RunCriteriaContainer { - type Label = BoxedRunCriteriaLabel; + type Label = RunCriteriaLabel; fn name(&self) -> Cow<'static, str> { match &self.inner { @@ -138,7 +138,7 @@ impl GraphNode for RunCriteriaContainer { } } - fn labels(&self) -> &[BoxedRunCriteriaLabel] { + fn labels(&self) -> &[RunCriteriaLabel] { if let Some(ref label) = self.label { std::slice::from_ref(label) } else { @@ -146,18 +146,18 @@ impl GraphNode for RunCriteriaContainer { } } - fn before(&self) -> &[BoxedRunCriteriaLabel] { + fn before(&self) -> &[RunCriteriaLabel] { &self.before } - fn after(&self) -> &[BoxedRunCriteriaLabel] { + fn after(&self) -> &[RunCriteriaLabel] { &self.after } } pub enum RunCriteriaDescriptorOrLabel { Descriptor(RunCriteriaDescriptor), - Label(BoxedRunCriteriaLabel), + Label(RunCriteriaLabel), } #[derive(Clone, Copy)] @@ -168,10 +168,10 @@ pub(crate) enum DuplicateLabelStrategy { pub struct RunCriteriaDescriptor { pub(crate) system: RunCriteriaSystem, - pub(crate) label: Option, + pub(crate) label: Option, pub(crate) duplicate_label_strategy: DuplicateLabelStrategy, - pub(crate) before: Vec, - pub(crate) after: Vec, + pub(crate) before: Vec, + pub(crate) after: Vec, } pub(crate) enum RunCriteriaSystem { @@ -212,12 +212,12 @@ where } } -impl IntoRunCriteria for L +impl IntoRunCriteria for L where - L: RunCriteriaLabel, + L: IntoRunCriteriaLabel, { fn into(self) -> RunCriteriaDescriptorOrLabel { - RunCriteriaDescriptorOrLabel::Label(Box::new(self)) + RunCriteriaDescriptorOrLabel::Label(self.as_label()) } } @@ -229,39 +229,42 @@ impl IntoRunCriteria for RunCriteria { pub trait RunCriteriaDescriptorCoercion { /// Assigns a label to the criteria. Must be unique. - fn label(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor; + fn label(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor; /// Assigns a label to the criteria. If the given label is already in use, /// this criteria will be discarded before initialization. - fn label_discard_if_duplicate(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor; + fn label_discard_if_duplicate(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor; /// Specifies that this criteria must be evaluated before a criteria with the given label. - fn before(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor; + fn before(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor; /// Specifies that this criteria must be evaluated after a criteria with the given label. - fn after(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor; + fn after(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor; } impl RunCriteriaDescriptorCoercion<()> for RunCriteriaDescriptor { - fn label(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.label = Some(Box::new(label)); + fn label(mut self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor { + self.label = Some(label.as_label()); self.duplicate_label_strategy = DuplicateLabelStrategy::Panic; self } - fn label_discard_if_duplicate(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.label = Some(Box::new(label)); + fn label_discard_if_duplicate( + mut self, + label: impl IntoRunCriteriaLabel, + ) -> RunCriteriaDescriptor { + self.label = Some(label.as_label()); self.duplicate_label_strategy = DuplicateLabelStrategy::Discard; self } - fn before(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.before.push(Box::new(label)); + fn before(mut self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor { + self.before.push(label.as_label()); self } - fn after(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.after.push(Box::new(label)); + fn after(mut self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor { + self.after.push(label.as_label()); self } } @@ -277,19 +280,19 @@ fn new_run_criteria_descriptor(system: BoxedSystem<(), ShouldRun>) -> RunCriteri } impl RunCriteriaDescriptorCoercion<()> for BoxedSystem<(), ShouldRun> { - fn label(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { + fn label(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor { new_run_criteria_descriptor(self).label(label) } - fn label_discard_if_duplicate(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { + fn label_discard_if_duplicate(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor { new_run_criteria_descriptor(self).label_discard_if_duplicate(label) } - fn before(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { + fn before(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor { new_run_criteria_descriptor(self).before(label) } - fn after(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { + fn after(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor { new_run_criteria_descriptor(self).after(label) } } @@ -298,33 +301,33 @@ impl RunCriteriaDescriptorCoercion for S where S: IntoSystem<(), ShouldRun, Param>, { - fn label(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { + fn label(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor { new_run_criteria_descriptor(Box::new(IntoSystem::into_system(self))).label(label) } - fn label_discard_if_duplicate(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { + fn label_discard_if_duplicate(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor { new_run_criteria_descriptor(Box::new(IntoSystem::into_system(self))) .label_discard_if_duplicate(label) } - fn before(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { + fn before(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor { new_run_criteria_descriptor(Box::new(IntoSystem::into_system(self))).before(label) } - fn after(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { + fn after(self, label: impl IntoRunCriteriaLabel) -> RunCriteriaDescriptor { new_run_criteria_descriptor(Box::new(IntoSystem::into_system(self))).after(label) } } pub struct RunCriteria { - label: BoxedRunCriteriaLabel, + label: RunCriteriaLabel, } impl RunCriteria { /// Constructs a new run criteria that will retrieve the result of the criteria `label` /// and pipe it as input to `system`. pub fn pipe

( - label: impl RunCriteriaLabel, + label: impl IntoRunCriteriaLabel, system: impl IntoSystem, ) -> RunCriteriaDescriptor { RunCriteriaDescriptor { @@ -332,7 +335,7 @@ impl RunCriteria { label: None, duplicate_label_strategy: DuplicateLabelStrategy::Panic, before: vec![], - after: vec![Box::new(label)], + after: vec![label.as_label()], } } } diff --git a/crates/bevy_ecs/src/schedule/stage.rs b/crates/bevy_ecs/src/schedule/stage.rs index 014423e2c4f13..23fae7a9e654e 100644 --- a/crates/bevy_ecs/src/schedule/stage.rs +++ b/crates/bevy_ecs/src/schedule/stage.rs @@ -4,11 +4,11 @@ use crate::{ prelude::IntoSystem, schedule::{ graph_utils::{self, DependencyGraphError}, - BoxedRunCriteria, BoxedRunCriteriaLabel, BoxedSystemLabel, DuplicateLabelStrategy, - ExclusiveSystemContainer, GraphNode, InsertionPoint, ParallelExecutor, - ParallelSystemContainer, ParallelSystemExecutor, RunCriteriaContainer, - RunCriteriaDescriptor, RunCriteriaDescriptorOrLabel, RunCriteriaInner, ShouldRun, - SingleThreadedExecutor, SystemContainer, SystemDescriptor, SystemSet, + BoxedRunCriteria, DuplicateLabelStrategy, ExclusiveSystemContainer, GraphNode, + InsertionPoint, ParallelExecutor, ParallelSystemContainer, ParallelSystemExecutor, + RunCriteriaContainer, RunCriteriaDescriptor, RunCriteriaDescriptorOrLabel, + RunCriteriaInner, RunCriteriaLabel, ShouldRun, SingleThreadedExecutor, SystemContainer, + SystemDescriptor, SystemLabel, SystemSet, }, world::{World, WorldId}, }; @@ -171,7 +171,7 @@ impl SystemStage { container.run_criteria_label = Some(label); } Some(RunCriteriaDescriptorOrLabel::Descriptor(criteria_descriptor)) => { - container.run_criteria_label = criteria_descriptor.label.clone(); + container.run_criteria_label = criteria_descriptor.label; container.run_criteria_index = Some(self.add_run_criteria_internal(criteria_descriptor)); } @@ -205,7 +205,7 @@ impl SystemStage { container.run_criteria_label = Some(label); } Some(RunCriteriaDescriptorOrLabel::Descriptor(criteria_descriptor)) => { - container.run_criteria_label = criteria_descriptor.label.clone(); + container.run_criteria_label = criteria_descriptor.label; container.run_criteria_index = Some(self.add_run_criteria_internal(criteria_descriptor)); } @@ -301,11 +301,11 @@ impl SystemStage { match system { SystemDescriptor::Exclusive(descriptor) => { descriptor.run_criteria = - Some(RunCriteriaDescriptorOrLabel::Label(label.clone())); + Some(RunCriteriaDescriptorOrLabel::Label(label)); } SystemDescriptor::Parallel(descriptor) => { descriptor.run_criteria = - Some(RunCriteriaDescriptorOrLabel::Label(label.clone())); + Some(RunCriteriaDescriptorOrLabel::Label(label)); } } } @@ -372,7 +372,7 @@ impl SystemStage { .enumerate() .filter_map(|(index, mut container)| { let new_index = index - filtered_criteria; - let label = container.label.clone(); + let label = container.label; if let Some(strategy) = uninitialized_criteria.get(&index) { if let Some(ref label) = label { if let Some(duplicate_index) = criteria_labels.get(label) { @@ -621,10 +621,8 @@ impl SystemStage { /// Returns a map of run criteria labels to their indices. fn process_run_criteria( &mut self, - ) -> Result< - HashMap, - DependencyGraphError>, - > { + ) -> Result, DependencyGraphError>> + { let graph = graph_utils::build_dependency_graph(&self.run_criteria); let order = graph_utils::topological_order(&graph)?; let mut order_inverted = order.iter().enumerate().collect::>(); @@ -637,7 +635,7 @@ impl SystemStage { criteria .label .as_ref() - .map(|label| (label.clone(), order_inverted[index].0)) + .map(|&label| (label, order_inverted[index].0)) }) .collect(); for criteria in &mut self.run_criteria { @@ -680,8 +678,8 @@ impl SystemStage { /// and run criteria. fn process_systems( systems: &mut Vec, - run_criteria_labels: &HashMap, -) -> Result<(), DependencyGraphError>> { + run_criteria_labels: &HashMap, +) -> Result<(), DependencyGraphError>> { let mut graph = graph_utils::build_dependency_graph(systems); let order = graph_utils::topological_order(&graph)?; let mut order_inverted = order.iter().enumerate().collect::>(); @@ -974,9 +972,9 @@ impl Stage for SystemStage { mod tests { use crate::{ schedule::{ - BoxedSystemLabel, ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion, + ExclusiveSystemDescriptorCoercion, IntoSystemLabel, ParallelSystemDescriptorCoercion, RunCriteria, RunCriteriaDescriptorCoercion, ShouldRun, SingleThreadedExecutor, Stage, - SystemSet, SystemStage, + SystemLabel, SystemSet, SystemStage, }, system::{In, IntoExclusiveSystem, Local, Query, ResMut}, world::World, @@ -1609,23 +1607,21 @@ mod tests { fn find_ambiguities_first_str_labels( systems: &[impl SystemContainer], - ) -> Vec<(BoxedSystemLabel, BoxedSystemLabel)> { + ) -> Vec<(SystemLabel, SystemLabel)> { find_ambiguities(systems) .drain(..) .map(|(index_a, index_b, _conflicts)| { ( - systems[index_a] + *systems[index_a] .labels() .iter() - .find(|a| (&***a).type_id() == std::any::TypeId::of::<&str>()) - .unwrap() - .clone(), - systems[index_b] + .find(|a| a.type_id() == std::any::TypeId::of::<&str>()) + .unwrap(), + *systems[index_b] .labels() .iter() - .find(|a| (&***a).type_id() == std::any::TypeId::of::<&str>()) - .unwrap() - .clone(), + .find(|a| a.type_id() == std::any::TypeId::of::<&str>()) + .unwrap(), ) }) .collect() @@ -1657,8 +1653,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1672,8 +1668,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1697,12 +1693,12 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("0"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("0"))) + ambiguities.contains(&("0".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "0".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 2); @@ -1716,8 +1712,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("0"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("0"))) + ambiguities.contains(&("0".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "0".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1729,8 +1725,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("0"), Box::new("1"))) - || ambiguities.contains(&(Box::new("1"), Box::new("0"))) + ambiguities.contains(&("0".as_label(), "1".as_label())) + || ambiguities.contains(&("1".as_label(), "0".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1742,8 +1738,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "2".as_label())) + || ambiguities.contains(&("2".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1756,8 +1752,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "2".as_label())) + || ambiguities.contains(&("2".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1780,8 +1776,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "2".as_label())) + || ambiguities.contains(&("2".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1810,28 +1806,28 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "2".as_label())) + || ambiguities.contains(&("2".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("3"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("3"))) + ambiguities.contains(&("3".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "3".as_label())) ); assert_eq!(ambiguities.len(), 6); @@ -1891,12 +1887,12 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "2".as_label())) ); assert_eq!(ambiguities.len(), 2); @@ -1925,28 +1921,28 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("5"))) - || ambiguities.contains(&(Box::new("5"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "5".as_label())) + || ambiguities.contains(&("5".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("5"))) - || ambiguities.contains(&(Box::new("5"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "5".as_label())) + || ambiguities.contains(&("5".as_label(), "2".as_label())) ); assert_eq!(ambiguities.len(), 6); @@ -1962,20 +1958,20 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("5"))) - || ambiguities.contains(&(Box::new("5"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "5".as_label())) + || ambiguities.contains(&("5".as_label(), "2".as_label())) ); assert_eq!(ambiguities.len(), 4); diff --git a/crates/bevy_ecs/src/schedule/state.rs b/crates/bevy_ecs/src/schedule/state.rs index 1693f0adce7e3..9e6eae5b6a9d5 100644 --- a/crates/bevy_ecs/src/schedule/state.rs +++ b/crates/bevy_ecs/src/schedule/state.rs @@ -1,6 +1,6 @@ use crate::{ schedule::{ - RunCriteriaDescriptor, RunCriteriaDescriptorCoercion, RunCriteriaLabel, ShouldRun, + IntoRunCriteriaLabel, RunCriteriaDescriptor, RunCriteriaDescriptorCoercion, ShouldRun, SystemSet, }, system::{In, IntoChainSystem, Local, Res, ResMut}, @@ -74,26 +74,29 @@ impl StateCallback { #[derive(Debug, PartialEq, Eq, Clone, Hash)] struct StateRunCriteriaLabel(T, StateCallback); -impl RunCriteriaLabel for StateRunCriteriaLabel +impl IntoRunCriteriaLabel for StateRunCriteriaLabel where T: StateData, { - fn dyn_clone(&self) -> Box { - Box::new(self.clone()) + fn as_str(&self) -> &'static str { + todo!() } } #[derive(Debug, PartialEq, Eq, Clone, Hash)] -struct DriverLabel(TypeId); -impl RunCriteriaLabel for DriverLabel { - fn dyn_clone(&self) -> Box { - Box::new(self.clone()) +struct DriverLabel(TypeId, &'static str); +impl IntoRunCriteriaLabel for DriverLabel { + fn type_id(&self) -> core::any::TypeId { + self.0 + } + fn as_str(&self) -> &'static str { + self.1 } } impl DriverLabel { fn of() -> Self { - Self(TypeId::of::()) + Self(TypeId::of::(), std::any::type_name::()) } } diff --git a/crates/bevy_ecs/src/schedule/system_container.rs b/crates/bevy_ecs/src/schedule/system_container.rs index a82969a5d4c32..57c4364a6cf67 100644 --- a/crates/bevy_ecs/src/schedule/system_container.rs +++ b/crates/bevy_ecs/src/schedule/system_container.rs @@ -2,15 +2,15 @@ use crate::{ component::ComponentId, query::Access, schedule::{ - BoxedAmbiguitySetLabel, BoxedRunCriteriaLabel, BoxedSystemLabel, ExclusiveSystemDescriptor, - GraphNode, ParallelSystemDescriptor, + AmbiguitySetLabel, ExclusiveSystemDescriptor, GraphNode, ParallelSystemDescriptor, + RunCriteriaLabel, SystemLabel, }, system::{ExclusiveSystem, System}, }; use std::borrow::Cow; /// System metadata like its name, labels, order requirements and component access. -pub trait SystemContainer: GraphNode

( - label: impl IntoRunCriteriaLabel, + label: impl RunCriteriaLabel, system: impl IntoSystem, ) -> RunCriteriaDescriptor { RunCriteriaDescriptor { diff --git a/crates/bevy_ecs/src/schedule/stage.rs b/crates/bevy_ecs/src/schedule/stage.rs index 23fae7a9e654e..a14a5db7be32a 100644 --- a/crates/bevy_ecs/src/schedule/stage.rs +++ b/crates/bevy_ecs/src/schedule/stage.rs @@ -7,8 +7,8 @@ use crate::{ BoxedRunCriteria, DuplicateLabelStrategy, ExclusiveSystemContainer, GraphNode, InsertionPoint, ParallelExecutor, ParallelSystemContainer, ParallelSystemExecutor, RunCriteriaContainer, RunCriteriaDescriptor, RunCriteriaDescriptorOrLabel, - RunCriteriaInner, RunCriteriaLabel, ShouldRun, SingleThreadedExecutor, SystemContainer, - SystemDescriptor, SystemLabel, SystemSet, + RunCriteriaInner, RunCriteriaLabelId, ShouldRun, SingleThreadedExecutor, SystemContainer, + SystemDescriptor, SystemLabelId, SystemSet, }, world::{World, WorldId}, }; @@ -621,7 +621,7 @@ impl SystemStage { /// Returns a map of run criteria labels to their indices. fn process_run_criteria( &mut self, - ) -> Result, DependencyGraphError>> + ) -> Result, DependencyGraphError>> { let graph = graph_utils::build_dependency_graph(&self.run_criteria); let order = graph_utils::topological_order(&graph)?; @@ -678,8 +678,8 @@ impl SystemStage { /// and run criteria. fn process_systems( systems: &mut Vec, - run_criteria_labels: &HashMap, -) -> Result<(), DependencyGraphError>> { + run_criteria_labels: &HashMap, +) -> Result<(), DependencyGraphError>> { let mut graph = graph_utils::build_dependency_graph(systems); let order = graph_utils::topological_order(&graph)?; let mut order_inverted = order.iter().enumerate().collect::>(); @@ -972,9 +972,9 @@ impl Stage for SystemStage { mod tests { use crate::{ schedule::{ - ExclusiveSystemDescriptorCoercion, IntoSystemLabel, ParallelSystemDescriptorCoercion, - RunCriteria, RunCriteriaDescriptorCoercion, ShouldRun, SingleThreadedExecutor, Stage, - SystemLabel, SystemSet, SystemStage, + ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion, RunCriteria, + RunCriteriaDescriptorCoercion, ShouldRun, SingleThreadedExecutor, Stage, SystemLabel, + SystemLabelId, SystemSet, SystemStage, }, system::{In, IntoExclusiveSystem, Local, Query, ResMut}, world::World, @@ -1607,7 +1607,7 @@ mod tests { fn find_ambiguities_first_str_labels( systems: &[impl SystemContainer], - ) -> Vec<(SystemLabel, SystemLabel)> { + ) -> Vec<(SystemLabelId, SystemLabelId)> { find_ambiguities(systems) .drain(..) .map(|(index_a, index_b, _conflicts)| { diff --git a/crates/bevy_ecs/src/schedule/state.rs b/crates/bevy_ecs/src/schedule/state.rs index 9e6eae5b6a9d5..99d76afa371f0 100644 --- a/crates/bevy_ecs/src/schedule/state.rs +++ b/crates/bevy_ecs/src/schedule/state.rs @@ -1,6 +1,6 @@ use crate::{ schedule::{ - IntoRunCriteriaLabel, RunCriteriaDescriptor, RunCriteriaDescriptorCoercion, ShouldRun, + RunCriteriaDescriptor, RunCriteriaDescriptorCoercion, RunCriteriaLabel, ShouldRun, SystemSet, }, system::{In, IntoChainSystem, Local, Res, ResMut}, @@ -85,7 +85,7 @@ where #[derive(Debug, PartialEq, Eq, Clone, Hash)] struct DriverLabel(TypeId, &'static str); -impl IntoRunCriteriaLabel for DriverLabel { +impl RunCriteriaLabel for DriverLabel { fn type_id(&self) -> core::any::TypeId { self.0 } diff --git a/crates/bevy_ecs/src/schedule/system_container.rs b/crates/bevy_ecs/src/schedule/system_container.rs index 57c4364a6cf67..51d0962489143 100644 --- a/crates/bevy_ecs/src/schedule/system_container.rs +++ b/crates/bevy_ecs/src/schedule/system_container.rs @@ -2,15 +2,15 @@ use crate::{ component::ComponentId, query::Access, schedule::{ - AmbiguitySetLabel, ExclusiveSystemDescriptor, GraphNode, ParallelSystemDescriptor, - RunCriteriaLabel, SystemLabel, + AmbiguitySetLabelId, ExclusiveSystemDescriptor, GraphNode, ParallelSystemDescriptor, + RunCriteriaLabelId, SystemLabelId, }, system::{ExclusiveSystem, System}, }; use std::borrow::Cow; /// System metadata like its name, labels, order requirements and component access. -pub trait SystemContainer: GraphNode