Deprecate .system (#3302)

# Objective

- Using `.system()` is no longer idiomatic.

## Solution

- Give a warning when using it
This commit is contained in:
Daniel McNab 2022-02-08 04:00:58 +00:00
parent 2f11c9dca8
commit 6615b7bf64
17 changed files with 157 additions and 128 deletions

View File

@ -430,7 +430,7 @@ impl App {
/// } /// }
/// ///
/// App::new() /// App::new()
/// .add_startup_system(my_startup_system.system()); /// .add_startup_system(my_startup_system);
/// ``` /// ```
pub fn add_startup_system<Params>( pub fn add_startup_system<Params>(
&mut self, &mut self,

View File

@ -558,6 +558,7 @@ pub fn free_unused_assets_system(asset_server: Res<AssetServer>) {
mod test { mod test {
use super::*; use super::*;
use crate::{loader::LoadedAsset, update_asset_storage_system}; use crate::{loader::LoadedAsset, update_asset_storage_system};
use bevy_app::App;
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_reflect::TypeUuid; use bevy_reflect::TypeUuid;
use bevy_utils::BoxedFuture; use bevy_utils::BoxedFuture;
@ -771,21 +772,13 @@ mod test {
asset_server.add_loader(FakePngLoader); asset_server.add_loader(FakePngLoader);
let assets = asset_server.register_asset_type::<PngAsset>(); let assets = asset_server.register_asset_type::<PngAsset>();
let mut world = World::new(); #[derive(SystemLabel, Clone, Hash, Debug, PartialEq, Eq)]
world.insert_resource(assets); struct FreeUnusedAssets;
world.insert_resource(asset_server); let mut app = App::new();
app.insert_resource(assets);
let mut tick = { app.insert_resource(asset_server);
let mut free_unused_assets_system = free_unused_assets_system.system(); app.add_system(free_unused_assets_system.label(FreeUnusedAssets));
free_unused_assets_system.initialize(&mut world); app.add_system(update_asset_storage_system::<PngAsset>.after(FreeUnusedAssets));
let mut update_asset_storage_system = update_asset_storage_system::<PngAsset>.system();
update_asset_storage_system.initialize(&mut world);
move |world: &mut World| {
free_unused_assets_system.run((), world);
update_asset_storage_system.run((), world);
}
};
fn load_asset(path: AssetPath, world: &World) -> HandleUntyped { fn load_asset(path: AssetPath, world: &World) -> HandleUntyped {
let asset_server = world.get_resource::<AssetServer>().unwrap(); let asset_server = world.get_resource::<AssetServer>().unwrap();
@ -813,37 +806,43 @@ mod test {
// --- // ---
let path: AssetPath = "fake.png".into(); let path: AssetPath = "fake.png".into();
assert_eq!(LoadState::NotLoaded, get_load_state(path.get_id(), &world)); assert_eq!(
LoadState::NotLoaded,
get_load_state(path.get_id(), &app.world)
);
// load the asset // load the asset
let handle = load_asset(path.clone(), &world); let handle = load_asset(path.clone(), &app.world);
let weak_handle = handle.clone_weak(); let weak_handle = handle.clone_weak();
// asset is loading // asset is loading
assert_eq!(LoadState::Loading, get_load_state(&handle, &world)); assert_eq!(LoadState::Loading, get_load_state(&handle, &app.world));
tick(&mut world); app.update();
// asset should exist and be loaded at this point // asset should exist and be loaded at this point
assert_eq!(LoadState::Loaded, get_load_state(&handle, &world)); assert_eq!(LoadState::Loaded, get_load_state(&handle, &app.world));
assert!(get_asset(&handle, &world).is_some()); assert!(get_asset(&handle, &app.world).is_some());
// after dropping the handle, next call to `tick` will prepare the assets for removal. // after dropping the handle, next call to `tick` will prepare the assets for removal.
drop(handle); drop(handle);
tick(&mut world); app.update();
assert_eq!(LoadState::Loaded, get_load_state(&weak_handle, &world)); assert_eq!(LoadState::Loaded, get_load_state(&weak_handle, &app.world));
assert!(get_asset(&weak_handle, &world).is_some()); assert!(get_asset(&weak_handle, &app.world).is_some());
// second call to tick will actually remove the asset. // second call to tick will actually remove the asset.
tick(&mut world); app.update();
assert_eq!(LoadState::Unloaded, get_load_state(&weak_handle, &world)); assert_eq!(
assert!(get_asset(&weak_handle, &world).is_none()); LoadState::Unloaded,
get_load_state(&weak_handle, &app.world)
);
assert!(get_asset(&weak_handle, &app.world).is_none());
// finally, reload the asset // finally, reload the asset
let handle = load_asset(path.clone(), &world); let handle = load_asset(path.clone(), &app.world);
assert_eq!(LoadState::Loading, get_load_state(&handle, &world)); assert_eq!(LoadState::Loading, get_load_state(&handle, &app.world));
tick(&mut world); app.update();
assert_eq!(LoadState::Loaded, get_load_state(&handle, &world)); assert_eq!(LoadState::Loaded, get_load_state(&handle, &app.world));
assert!(get_asset(&handle, &world).is_some()); assert!(get_asset(&handle, &app.world).is_some());
} }
#[test] #[test]

View File

@ -79,7 +79,7 @@ impl Default for FixedTimestep {
fn default() -> Self { fn default() -> Self {
Self { Self {
state: LocalFixedTimestepState::default(), state: LocalFixedTimestepState::default(),
internal_system: Box::new(Self::prepare_system.system()), internal_system: Box::new(IntoSystem::into_system(Self::prepare_system)),
} }
} }
} }

View File

@ -806,7 +806,7 @@ impl<'w, 's, T: Fetch<'w, 's>> Fetch<'w, 's> for OptionFetch<T> {
/// } /// }
/// } /// }
/// } /// }
/// # print_moving_objects_system.system(); /// # bevy_ecs::system::assert_is_system(print_moving_objects_system);
/// ``` /// ```
#[derive(Clone)] #[derive(Clone)]
pub struct ChangeTrackers<T: Component> { pub struct ChangeTrackers<T: Component> {

View File

@ -65,7 +65,7 @@ where
/// println!("{} is looking lovely today!", name.name); /// println!("{} is looking lovely today!", name.name);
/// } /// }
/// } /// }
/// # compliment_entity_system.system(); /// # bevy_ecs::system::assert_is_system(compliment_entity_system);
/// ``` /// ```
pub struct With<T>(PhantomData<T>); pub struct With<T>(PhantomData<T>);
@ -188,7 +188,7 @@ unsafe impl<T> ReadOnlyFetch for WithFetch<T> {}
/// println!("{} has no permit!", name.name); /// println!("{} has no permit!", name.name);
/// } /// }
/// } /// }
/// # no_permit_system.system(); /// # bevy_ecs::system::assert_is_system(no_permit_system);
/// ``` /// ```
pub struct Without<T>(PhantomData<T>); pub struct Without<T>(PhantomData<T>);
@ -317,7 +317,7 @@ unsafe impl<T> ReadOnlyFetch for WithoutFetch<T> {}
/// println!("Entity {:?} got a new style or color", entity); /// println!("Entity {:?} got a new style or color", entity);
/// } /// }
/// } /// }
/// # print_cool_entity_system.system(); /// # bevy_ecs::system::assert_is_system(print_cool_entity_system);
/// ``` /// ```
pub struct Or<T>(pub T); pub struct Or<T>(pub T);
@ -619,7 +619,7 @@ impl_tick_filter!(
/// } /// }
/// } /// }
/// ///
/// # print_add_name_component.system(); /// # bevy_ecs::system::assert_is_system(print_add_name_component);
/// ``` /// ```
Added, Added,
/// The [`FetchState`] of [`Added`]. /// The [`FetchState`] of [`Added`].
@ -662,7 +662,7 @@ impl_tick_filter!(
/// } /// }
/// } /// }
/// ///
/// # print_moving_objects_system.system(); /// # bevy_ecs::system::assert_is_system(print_moving_objects_system);
/// ``` /// ```
Changed, Changed,
/// The [`FetchState`] of [`Changed`]. /// The [`FetchState`] of [`Changed`].

View File

@ -235,7 +235,7 @@ where
{ {
fn into(self) -> RunCriteriaDescriptorOrLabel { fn into(self) -> RunCriteriaDescriptorOrLabel {
RunCriteriaDescriptorOrLabel::Descriptor(new_run_criteria_descriptor(Box::new( RunCriteriaDescriptorOrLabel::Descriptor(new_run_criteria_descriptor(Box::new(
self.system(), IntoSystem::into_system(self),
))) )))
} }
} }
@ -333,19 +333,20 @@ where
S: IntoSystem<(), ShouldRun, Param>, S: IntoSystem<(), ShouldRun, Param>,
{ {
fn label(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { fn label(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor {
new_run_criteria_descriptor(Box::new(self.system())).label(label) 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 RunCriteriaLabel) -> RunCriteriaDescriptor {
new_run_criteria_descriptor(Box::new(self.system())).label_discard_if_duplicate(label) 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 RunCriteriaLabel) -> RunCriteriaDescriptor {
new_run_criteria_descriptor(Box::new(self.system())).before(label) new_run_criteria_descriptor(Box::new(IntoSystem::into_system(self))).before(label)
} }
fn after(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { fn after(self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor {
new_run_criteria_descriptor(Box::new(self.system())).after(label) new_run_criteria_descriptor(Box::new(IntoSystem::into_system(self))).after(label)
} }
} }
@ -366,6 +367,8 @@ impl RunCriteria {
pub trait RunCriteriaPiping { pub trait RunCriteriaPiping {
/// See [`RunCriteria::pipe()`]. /// See [`RunCriteria::pipe()`].
// TODO: Support `IntoSystem` here instead, and stop using
// `IntoSystem::into_system` in the call sites
fn pipe(self, system: impl System<In = ShouldRun, Out = ShouldRun>) -> RunCriteriaDescriptor; fn pipe(self, system: impl System<In = ShouldRun, Out = ShouldRun>) -> RunCriteriaDescriptor;
} }

View File

@ -312,7 +312,7 @@ impl SystemStage {
mut self, mut self,
system: S, system: S,
) -> Self { ) -> Self {
self.set_run_criteria(system.system()); self.set_run_criteria(system);
self self
} }
@ -320,7 +320,8 @@ impl SystemStage {
&mut self, &mut self,
system: S, system: S,
) -> &mut Self { ) -> &mut Self {
self.stage_run_criteria.set(Box::new(system.system())); self.stage_run_criteria
.set(Box::new(IntoSystem::into_system(system)));
self self
} }
@ -1513,17 +1514,15 @@ mod tests {
.after("0") .after("0")
.with_run_criteria(every_other_time.label("every other time")), .with_run_criteria(every_other_time.label("every other time")),
) )
.with_system(make_parallel(2).label("2").after("1").with_run_criteria(
RunCriteria::pipe("every other time", IntoSystem::into_system(eot_piped)),
))
.with_system( .with_system(
make_parallel(2) make_parallel(3).label("3").after("2").with_run_criteria(
.label("2") "every other time"
.after("1") .pipe(IntoSystem::into_system(eot_piped))
.with_run_criteria(RunCriteria::pipe("every other time", eot_piped.system())), .label("piped"),
) ),
.with_system(
make_parallel(3)
.label("3")
.after("2")
.with_run_criteria("every other time".pipe(eot_piped.system()).label("piped")),
) )
.with_system(make_parallel(4).after("3").with_run_criteria("piped")); .with_system(make_parallel(4).after("3").with_run_criteria("piped"));
for _ in 0..4 { for _ in 0..4 {

View File

@ -56,7 +56,7 @@ where
S: IntoSystem<(), (), Params>, S: IntoSystem<(), (), Params>,
{ {
fn into_descriptor(self) -> SystemDescriptor { fn into_descriptor(self) -> SystemDescriptor {
new_parallel_descriptor(Box::new(self.system())).into_descriptor() new_parallel_descriptor(Box::new(IntoSystem::into_system(self))).into_descriptor()
} }
} }
@ -174,23 +174,24 @@ where
self, self,
run_criteria: impl IntoRunCriteria<Marker>, run_criteria: impl IntoRunCriteria<Marker>,
) -> ParallelSystemDescriptor { ) -> ParallelSystemDescriptor {
new_parallel_descriptor(Box::new(self.system())).with_run_criteria(run_criteria) new_parallel_descriptor(Box::new(IntoSystem::into_system(self)))
.with_run_criteria(run_criteria)
} }
fn label(self, label: impl SystemLabel) -> ParallelSystemDescriptor { fn label(self, label: impl SystemLabel) -> ParallelSystemDescriptor {
new_parallel_descriptor(Box::new(self.system())).label(label) new_parallel_descriptor(Box::new(IntoSystem::into_system(self))).label(label)
} }
fn before(self, label: impl SystemLabel) -> ParallelSystemDescriptor { fn before(self, label: impl SystemLabel) -> ParallelSystemDescriptor {
new_parallel_descriptor(Box::new(self.system())).before(label) new_parallel_descriptor(Box::new(IntoSystem::into_system(self))).before(label)
} }
fn after(self, label: impl SystemLabel) -> ParallelSystemDescriptor { fn after(self, label: impl SystemLabel) -> ParallelSystemDescriptor {
new_parallel_descriptor(Box::new(self.system())).after(label) new_parallel_descriptor(Box::new(IntoSystem::into_system(self))).after(label)
} }
fn in_ambiguity_set(self, set: impl AmbiguitySetLabel) -> ParallelSystemDescriptor { fn in_ambiguity_set(self, set: impl AmbiguitySetLabel) -> ParallelSystemDescriptor {
new_parallel_descriptor(Box::new(self.system())).in_ambiguity_set(set) new_parallel_descriptor(Box::new(IntoSystem::into_system(self))).in_ambiguity_set(set)
} }
} }

View File

@ -78,7 +78,7 @@ impl<'w, 's> Commands<'w, 's> {
/// // adds a single component to the entity /// // adds a single component to the entity
/// .insert(Label("hello world")); /// .insert(Label("hello world"));
/// } /// }
/// # example_system.system(); /// # bevy_ecs::system::assert_is_system(example_system);
/// ``` /// ```
pub fn spawn<'a>(&'a mut self) -> EntityCommands<'w, 's, 'a> { pub fn spawn<'a>(&'a mut self) -> EntityCommands<'w, 's, 'a> {
let entity = self.entities.reserve_entity(); let entity = self.entities.reserve_entity();
@ -156,7 +156,7 @@ impl<'w, 's> Commands<'w, 's> {
/// // or insert single components like this: /// // or insert single components like this:
/// .insert(Label("hello world")); /// .insert(Label("hello world"));
/// } /// }
/// # example_system.system(); /// # bevy_ecs::system::assert_is_system(example_system);
/// ``` /// ```
pub fn spawn_bundle<'a, T: Bundle>(&'a mut self, bundle: T) -> EntityCommands<'w, 's, 'a> { pub fn spawn_bundle<'a, T: Bundle>(&'a mut self, bundle: T) -> EntityCommands<'w, 's, 'a> {
let mut e = self.spawn(); let mut e = self.spawn();
@ -188,7 +188,7 @@ impl<'w, 's> Commands<'w, 's> {
/// // adds a single component to the entity /// // adds a single component to the entity
/// .insert(Label("hello world")); /// .insert(Label("hello world"));
/// } /// }
/// # example_system.system(); /// # bevy_ecs::system::assert_is_system(example_system);
/// ``` /// ```
#[track_caller] #[track_caller]
pub fn entity<'a>(&'a mut self, entity: Entity) -> EntityCommands<'w, 's, 'a> { pub fn entity<'a>(&'a mut self, entity: Entity) -> EntityCommands<'w, 's, 'a> {
@ -232,7 +232,7 @@ impl<'w, 's> Commands<'w, 's> {
/// ), /// ),
/// ]); /// ]);
/// # } /// # }
/// # system.system(); /// # bevy_ecs::system::assert_is_system(system);
/// ``` /// ```
pub fn spawn_batch<I>(&mut self, bundles_iter: I) pub fn spawn_batch<I>(&mut self, bundles_iter: I)
where where
@ -281,7 +281,7 @@ impl<'w, 's> Commands<'w, 's> {
/// high_score: 0, /// high_score: 0,
/// }); /// });
/// # } /// # }
/// # system.system(); /// # bevy_ecs::system::assert_is_system(system);
/// ``` /// ```
pub fn insert_resource<T: Resource>(&mut self, resource: T) { pub fn insert_resource<T: Resource>(&mut self, resource: T) {
self.queue.push(InsertResource { resource }) self.queue.push(InsertResource { resource })
@ -304,7 +304,7 @@ impl<'w, 's> Commands<'w, 's> {
/// # fn system(mut commands: Commands) { /// # fn system(mut commands: Commands) {
/// commands.remove_resource::<Scoreboard>(); /// commands.remove_resource::<Scoreboard>();
/// # } /// # }
/// # system.system(); /// # bevy_ecs::system::assert_is_system(system);
/// ``` /// ```
pub fn remove_resource<T: Resource>(&mut self) { pub fn remove_resource<T: Resource>(&mut self) {
self.queue.push(RemoveResource::<T> { self.queue.push(RemoveResource::<T> {
@ -345,7 +345,7 @@ impl<'w, 's> Commands<'w, 's> {
/// }, /// },
/// }); /// });
/// } /// }
/// # add_combat_stats_system.system(); /// # bevy_ecs::system::assert_is_system(add_combat_stats_system);
/// ``` /// ```
pub fn add<C: Command>(&mut self, command: C) { pub fn add<C: Command>(&mut self, command: C) {
self.queue.push(command); self.queue.push(command);
@ -369,7 +369,7 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
/// fn my_system(mut commands: Commands) { /// fn my_system(mut commands: Commands) {
/// let entity_id = commands.spawn().id(); /// let entity_id = commands.spawn().id();
/// } /// }
/// # my_system.system(); /// # bevy_ecs::system::assert_is_system(my_system);
/// ``` /// ```
#[inline] #[inline]
#[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."] #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]
@ -406,7 +406,7 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
/// defense: Defense(20), /// defense: Defense(20),
/// }); /// });
/// } /// }
/// # add_combat_stats_system.system(); /// # bevy_ecs::system::assert_is_system(add_combat_stats_system);
/// ``` /// ```
pub fn insert_bundle(&mut self, bundle: impl Bundle) -> &mut Self { pub fn insert_bundle(&mut self, bundle: impl Bundle) -> &mut Self {
self.commands.add(InsertBundle { self.commands.add(InsertBundle {
@ -440,7 +440,7 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
/// commands.spawn().insert_bundle((Component1, Component2)); /// commands.spawn().insert_bundle((Component1, Component2));
/// commands.spawn_bundle((Component1, Component2)); /// commands.spawn_bundle((Component1, Component2));
/// } /// }
/// # example_system.system(); /// # bevy_ecs::system::assert_is_system(example_system);
/// ``` /// ```
pub fn insert(&mut self, component: impl Component) -> &mut Self { pub fn insert(&mut self, component: impl Component) -> &mut Self {
self.commands.add(Insert { self.commands.add(Insert {
@ -470,7 +470,7 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
/// fn remove_combat_stats_system(mut commands: Commands, player: Res<PlayerEntity>) { /// fn remove_combat_stats_system(mut commands: Commands, player: Res<PlayerEntity>) {
/// commands.entity(player.entity).remove_bundle::<CombatBundle>(); /// commands.entity(player.entity).remove_bundle::<CombatBundle>();
/// } /// }
/// # remove_combat_stats_system.system(); /// # bevy_ecs::system::assert_is_system(remove_combat_stats_system);
/// ``` /// ```
pub fn remove_bundle<T>(&mut self) -> &mut Self pub fn remove_bundle<T>(&mut self) -> &mut Self
where where
@ -499,7 +499,7 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
/// fn convert_enemy_system(mut commands: Commands, enemy: Res<TargetEnemy>) { /// fn convert_enemy_system(mut commands: Commands, enemy: Res<TargetEnemy>) {
/// commands.entity(enemy.entity).remove::<Enemy>(); /// commands.entity(enemy.entity).remove::<Enemy>();
/// } /// }
/// # convert_enemy_system.system(); /// # bevy_ecs::system::assert_is_system(convert_enemy_system);
/// ``` /// ```
pub fn remove<T>(&mut self) -> &mut Self pub fn remove<T>(&mut self) -> &mut Self
where where
@ -530,7 +530,7 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
/// { /// {
/// commands.entity(character_to_remove.entity).despawn(); /// commands.entity(character_to_remove.entity).despawn();
/// } /// }
/// # remove_character_system.system(); /// # bevy_ecs::system::assert_is_system(remove_character_system);
/// ``` /// ```
pub fn despawn(&mut self) { pub fn despawn(&mut self) {
self.commands.add(Despawn { self.commands.add(Despawn {

View File

@ -107,7 +107,7 @@ where
{ {
fn exclusive_system(self) -> ExclusiveSystemCoerced { fn exclusive_system(self) -> ExclusiveSystemCoerced {
ExclusiveSystemCoerced { ExclusiveSystemCoerced {
system: Box::new(self.system()), system: Box::new(IntoSystem::into_system(self)),
archetype_generation: ArchetypeGeneration::initial(), archetype_generation: ArchetypeGeneration::initial(),
} }
} }

View File

@ -249,15 +249,35 @@ impl<P: SystemParam + 'static> System for ParamSystem<P> {
/// ///
/// fn my_system_function(an_usize_resource: Res<usize>) {} /// fn my_system_function(an_usize_resource: Res<usize>) {}
/// ///
/// let system = my_system_function.system(); /// let system = IntoSystem::system(my_system_function);
/// ``` /// ```
// This trait has to be generic because we have potentially overlapping impls, in particular // This trait has to be generic because we have potentially overlapping impls, in particular
// because Rust thinks a type could impl multiple different `FnMut` combinations // because Rust thinks a type could impl multiple different `FnMut` combinations
// even though none can currently // even though none can currently
pub trait IntoSystem<In, Out, Params> { pub trait IntoSystem<In, Out, Params>: Sized {
type System: System<In = In, Out = Out>; type System: System<In = In, Out = Out>;
/// Turns this value into its corresponding [`System`]. /// Turns this value into its corresponding [`System`].
fn system(self) -> Self::System; ///
/// Use of this method was formerly required whenever adding a `system` to an `App`.
/// or other cases where a system is required.
/// However, since [#2398](https://github.com/bevyengine/bevy/pull/2398),
/// this is no longer required.
///
/// In future, this method will be removed.
///
/// One use of this method is to assert that a given function is a valid system.
/// For this case, use [`bevy_ecs::system::assert_is_system`] instead.
///
/// [`bevy_ecs::system::assert_is_system`]: [`crate::system::assert_is_system`]:
#[deprecated(
since = "0.7.0",
note = "`.system()` is no longer needed, as methods which accept systems will convert functions into a system automatically"
)]
fn system(self) -> Self::System {
IntoSystem::into_system(self)
}
/// Turns this value into its corresponding [`System`].
fn into_system(this: Self) -> Self::System;
} }
pub struct AlreadyWasSystem; pub struct AlreadyWasSystem;
@ -265,8 +285,8 @@ pub struct AlreadyWasSystem;
// Systems implicitly implement IntoSystem // Systems implicitly implement IntoSystem
impl<In, Out, Sys: System<In = In, Out = Out>> IntoSystem<In, Out, AlreadyWasSystem> for Sys { impl<In, Out, Sys: System<In = In, Out = Out>> IntoSystem<In, Out, AlreadyWasSystem> for Sys {
type System = Sys; type System = Sys;
fn system(self) -> Sys { fn into_system(this: Self) -> Sys {
self this
} }
} }
@ -285,7 +305,7 @@ impl<In, Out, Sys: System<In = In, Out = Out>> IntoSystem<In, Out, AlreadyWasSys
/// use bevy_ecs::prelude::*; /// use bevy_ecs::prelude::*;
/// ///
/// fn main() { /// fn main() {
/// let mut square_system = square.system(); /// let mut square_system = IntoSystem::into_system(square);
/// ///
/// let mut world = World::default(); /// let mut world = World::default();
/// square_system.initialize(&mut world); /// square_system.initialize(&mut world);
@ -373,7 +393,7 @@ where
self, self,
f: impl FnOnce(&mut <<Param as SystemParam>::Fetch as SystemParamState>::Config), f: impl FnOnce(&mut <<Param as SystemParam>::Fetch as SystemParamState>::Config),
) -> Self::System { ) -> Self::System {
self.system().config(f) IntoSystem::into_system(self).config(f)
} }
} }
@ -388,9 +408,9 @@ where
F: SystemParamFunction<In, Out, Param, Marker> + Send + Sync + 'static, F: SystemParamFunction<In, Out, Param, Marker> + Send + Sync + 'static,
{ {
type System = FunctionSystem<In, Out, Param, Marker, F>; type System = FunctionSystem<In, Out, Param, Marker, F>;
fn system(self) -> Self::System { fn into_system(func: Self) -> Self::System {
FunctionSystem { FunctionSystem {
func: self, func,
param_state: None, param_state: None,
config: Some(<Param::Fetch as SystemParamState>::default_config()), config: Some(<Param::Fetch as SystemParamState>::default_config()),
system_meta: SystemMeta::new::<F>(), system_meta: SystemMeta::new::<F>(),

View File

@ -30,7 +30,7 @@
//! } //! }
//! round.0 += 1; //! round.0 += 1;
//! } //! }
//! # update_score_system.system(); //! # bevy_ecs::system::assert_is_system(update_score_system);
//! ``` //! ```
//! //!
//! # System ordering //! # System ordering
@ -83,6 +83,13 @@ pub use system::*;
pub use system_chaining::*; pub use system_chaining::*;
pub use system_param::*; pub use system_param::*;
pub fn assert_is_system<In, Out, Params, S: IntoSystem<In, Out, Params>>(sys: S) {
if false {
// Check it can be converted into a system
IntoSystem::into_system(sys);
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::any::TypeId; use std::any::TypeId;
@ -126,7 +133,7 @@ mod tests {
} }
} }
let mut system = sys.system(); let mut system = IntoSystem::into_system(sys);
let mut world = World::new(); let mut world = World::new();
world.spawn().insert(A); world.spawn().insert(A);
@ -584,8 +591,8 @@ mod tests {
fn sys_y(_: Res<A>, _: ResMut<B>, _: Query<(&C, &mut D)>) {} fn sys_y(_: Res<A>, _: ResMut<B>, _: Query<(&C, &mut D)>) {}
let mut world = World::default(); let mut world = World::default();
let mut x = sys_x.system(); let mut x = IntoSystem::into_system(sys_x);
let mut y = sys_y.system(); let mut y = IntoSystem::into_system(sys_y);
x.initialize(&mut world); x.initialize(&mut world);
y.initialize(&mut world); y.initialize(&mut world);
@ -613,11 +620,11 @@ mod tests {
let mut world = World::default(); let mut world = World::default();
world.spawn().insert(A).insert(C); world.spawn().insert(A).insert(C);
let mut without_filter = without_filter.system(); let mut without_filter = IntoSystem::into_system(without_filter);
without_filter.initialize(&mut world); without_filter.initialize(&mut world);
without_filter.run((), &mut world); without_filter.run((), &mut world);
let mut with_filter = with_filter.system(); let mut with_filter = IntoSystem::into_system(with_filter);
with_filter.initialize(&mut world); with_filter.initialize(&mut world);
with_filter.run((), &mut world); with_filter.run((), &mut world);
} }
@ -664,8 +671,8 @@ mod tests {
) { ) {
} }
let mut world = World::default(); let mut world = World::default();
let mut x = sys_x.system(); let mut x = IntoSystem::into_system(sys_x);
let mut y = sys_y.system(); let mut y = IntoSystem::into_system(sys_y);
x.initialize(&mut world); x.initialize(&mut world);
y.initialize(&mut world); y.initialize(&mut world);
} }

View File

@ -53,7 +53,7 @@ use thiserror::Error;
/// # fn system( /// # fn system(
/// query: Query<(&ComponentA, &ComponentB)> /// query: Query<(&ComponentA, &ComponentB)>
/// # ) {} /// # ) {}
/// # system.system(); /// # bevy_ecs::system::assert_is_system(system);
/// ``` /// ```
/// ///
/// ## Mutable component access /// ## Mutable component access
@ -74,7 +74,7 @@ use thiserror::Error;
/// // `ComponentA` is accessed mutably, while `ComponentB` is accessed immutably. /// // `ComponentA` is accessed mutably, while `ComponentB` is accessed immutably.
/// mut query: Query<(&mut ComponentA, &ComponentB)> /// mut query: Query<(&mut ComponentA, &ComponentB)>
/// # ) {} /// # ) {}
/// # system.system(); /// # bevy_ecs::system::assert_is_system(system);
/// ``` /// ```
/// ///
/// Two systems cannot be executed in parallel if both access a certain component and /// Two systems cannot be executed in parallel if both access a certain component and
@ -99,7 +99,7 @@ use thiserror::Error;
/// # fn system( /// # fn system(
/// query: Query<(Entity, &ComponentA, &ComponentB)> /// query: Query<(Entity, &ComponentA, &ComponentB)>
/// # ) {} /// # ) {}
/// # system.system(); /// # bevy_ecs::system::assert_is_system(system);
/// ``` /// ```
/// ///
/// ## Query filtering /// ## Query filtering
@ -119,7 +119,7 @@ use thiserror::Error;
/// // `ComponentC` data won't be accessed, but only entities that contain it will be queried. /// // `ComponentC` data won't be accessed, but only entities that contain it will be queried.
/// query: Query<(&ComponentA, &ComponentB), With<ComponentC>> /// query: Query<(&ComponentA, &ComponentB), With<ComponentC>>
/// # ) {} /// # ) {}
/// # system.system(); /// # bevy_ecs::system::assert_is_system(system);
/// ``` /// ```
/// ///
/// If you need to apply more filters in a single query, group them into a tuple: /// If you need to apply more filters in a single query, group them into a tuple:
@ -136,7 +136,7 @@ use thiserror::Error;
/// // Similar to the previous query, but with the addition of a `Changed` filter. /// // Similar to the previous query, but with the addition of a `Changed` filter.
/// query: Query<(&ComponentA, &ComponentB), (With<ComponentC>, Changed<ComponentA>)> /// query: Query<(&ComponentA, &ComponentB), (With<ComponentC>, Changed<ComponentA>)>
/// # ) {} /// # ) {}
/// # system.system(); /// # bevy_ecs::system::assert_is_system(system);
/// ``` /// ```
/// ///
/// The following list contains all the available query filters: /// The following list contains all the available query filters:
@ -162,7 +162,7 @@ use thiserror::Error;
/// # fn system( /// # fn system(
/// query: Query<(&ComponentA, Option<&ComponentB>)> /// query: Query<(&ComponentA, Option<&ComponentB>)>
/// # ) {} /// # ) {}
/// # system.system(); /// # bevy_ecs::system::assert_is_system(system);
/// ``` /// ```
/// ///
/// If an entity does not contain a component, its corresponding query result value will be /// If an entity does not contain a component, its corresponding query result value will be
@ -184,13 +184,13 @@ use thiserror::Error;
/// // This is correct, but can be avoided. /// // This is correct, but can be avoided.
/// query: Query<(&MyComponent,)> /// query: Query<(&MyComponent,)>
/// # ) {} /// # ) {}
/// # tuple_system.system(); /// # bevy_ecs::system::assert_is_system(tuple_system);
/// ///
/// # fn non_tuple_system( /// # fn non_tuple_system(
/// // This is the preferred method. /// // This is the preferred method.
/// query: Query<&MyComponent> /// query: Query<&MyComponent>
/// # ) {} /// # ) {}
/// # non_tuple_system.system(); /// # bevy_ecs::system::assert_is_system(non_tuple_system);
/// ``` /// ```
/// ///
/// # Usage of query results /// # Usage of query results
@ -217,7 +217,7 @@ use thiserror::Error;
/// // `&ComponentA` and `&ComponentB` types. /// // `&ComponentA` and `&ComponentB` types.
/// } /// }
/// } /// }
/// # immutable_query_system.system(); /// # bevy_ecs::system::assert_is_system(immutable_query_system);
/// ///
/// fn mutable_query_system(mut query: Query<(&mut ComponentA, &ComponentB)>) { /// fn mutable_query_system(mut query: Query<(&mut ComponentA, &ComponentB)>) {
/// for (mut a, b) in query.iter_mut() { /// for (mut a, b) in query.iter_mut() {
@ -225,7 +225,7 @@ use thiserror::Error;
/// // Note the usage of `mut` in the tuple and the call to `iter_mut` instead of `iter`. /// // Note the usage of `mut` in the tuple and the call to `iter_mut` instead of `iter`.
/// } /// }
/// } /// }
/// # mutable_query_system.system(); /// # bevy_ecs::system::assert_is_system(mutable_query_system);
/// ``` /// ```
/// ///
/// ## Getting the query result for a particular entity /// ## Getting the query result for a particular entity
@ -296,7 +296,7 @@ where
/// println!("Say hello to {}!", player.name); /// println!("Say hello to {}!", player.name);
/// } /// }
/// } /// }
/// # report_names_system.system(); /// # bevy_ecs::system::assert_is_system(report_names_system);
/// ``` /// ```
#[inline] #[inline]
pub fn iter(&'s self) -> QueryIter<'w, 's, Q, Q::ReadOnlyFetch, F> { pub fn iter(&'s self) -> QueryIter<'w, 's, Q, Q::ReadOnlyFetch, F> {
@ -326,7 +326,7 @@ where
/// velocity.y -= 9.8 * DELTA; /// velocity.y -= 9.8 * DELTA;
/// } /// }
/// } /// }
/// # gravity_system.system(); /// # bevy_ecs::system::assert_is_system(gravity_system);
/// ``` /// ```
#[inline] #[inline]
pub fn iter_mut(&mut self) -> QueryIter<'_, '_, Q, Q::Fetch, F> { pub fn iter_mut(&mut self) -> QueryIter<'_, '_, Q, Q::Fetch, F> {
@ -451,7 +451,7 @@ where
/// println!("Say hello to {}!", player.name); /// println!("Say hello to {}!", player.name);
/// }); /// });
/// } /// }
/// # report_names_system.system(); /// # bevy_ecs::system::assert_is_system(report_names_system);
/// ``` /// ```
#[inline] #[inline]
pub fn for_each<FN: FnMut(<Q::ReadOnlyFetch as Fetch<'w, 's>>::Item)>(&'s self, f: FN) { pub fn for_each<FN: FnMut(<Q::ReadOnlyFetch as Fetch<'w, 's>>::Item)>(&'s self, f: FN) {
@ -487,7 +487,7 @@ where
/// velocity.y -= 9.8 * DELTA; /// velocity.y -= 9.8 * DELTA;
/// }); /// });
/// } /// }
/// # gravity_system.system(); /// # bevy_ecs::system::assert_is_system(gravity_system);
/// ``` /// ```
#[inline] #[inline]
pub fn for_each_mut<'a, FN: FnMut(<Q::Fetch as Fetch<'a, 'a>>::Item)>(&'a mut self, f: FN) { pub fn for_each_mut<'a, FN: FnMut(<Q::Fetch as Fetch<'a, 'a>>::Item)>(&'a mut self, f: FN) {
@ -580,7 +580,7 @@ where
/// println!("{}", selected_character.name); /// println!("{}", selected_character.name);
/// } /// }
/// } /// }
/// # print_selected_character_name_system.system(); /// # bevy_ecs::system::assert_is_system(print_selected_character_name_system);
/// ``` /// ```
#[inline] #[inline]
pub fn get( pub fn get(
@ -621,7 +621,7 @@ where
/// health.0 -= 1; /// health.0 -= 1;
/// } /// }
/// } /// }
/// # poison_system.system(); /// # bevy_ecs::system::assert_is_system(poison_system);
/// ``` /// ```
#[inline] #[inline]
pub fn get_mut( pub fn get_mut(
@ -690,7 +690,7 @@ where
/// println!("{}", selected_character.name); /// println!("{}", selected_character.name);
/// } /// }
/// } /// }
/// # print_selected_character_name_system.system(); /// # bevy_ecs::system::assert_is_system(print_selected_character_name_system);
/// ``` /// ```
#[inline] #[inline]
pub fn get_component<T: Component>(&self, entity: Entity) -> Result<&T, QueryComponentError> { pub fn get_component<T: Component>(&self, entity: Entity) -> Result<&T, QueryComponentError> {
@ -741,7 +741,7 @@ where
/// health.0 -= 1; /// health.0 -= 1;
/// } /// }
/// } /// }
/// # poison_system.system(); /// # bevy_ecs::system::assert_is_system(poison_system);
/// ``` /// ```
#[inline] #[inline]
pub fn get_component_mut<T: Component>( pub fn get_component_mut<T: Component>(
@ -809,7 +809,7 @@ where
/// let player_position = query.single(); /// let player_position = query.single();
/// // do something with player_position /// // do something with player_position
/// } /// }
/// # player_system.system(); /// # bevy_ecs::system::assert_is_system(player_system);
/// ``` /// ```
/// ///
/// # Panics /// # Panics
@ -850,7 +850,7 @@ where
/// } /// }
/// } /// }
/// } /// }
/// # player_scoring_system.system(); /// # bevy_ecs::system::assert_is_system(player_scoring_system);
/// ``` /// ```
pub fn get_single( pub fn get_single(
&'s self, &'s self,
@ -885,7 +885,7 @@ where
/// let mut health = query.single_mut(); /// let mut health = query.single_mut();
/// health.0 += 1; /// health.0 += 1;
/// } /// }
/// # regenerate_player_health_system.system(); /// # bevy_ecs::system::assert_is_system(regenerate_player_health_system);
/// ``` /// ```
/// ///
/// # Panics /// # Panics
@ -917,7 +917,7 @@ where
/// let mut health = query.get_single_mut().expect("Error: Could not find a single player."); /// let mut health = query.get_single_mut().expect("Error: Could not find a single player.");
/// health.0 += 1; /// health.0 += 1;
/// } /// }
/// # regenerate_player_health_system.system(); /// # bevy_ecs::system::assert_is_system(regenerate_player_health_system);
/// ``` /// ```
pub fn get_single_mut( pub fn get_single_mut(
&mut self, &mut self,
@ -954,7 +954,7 @@ where
/// score.0 += 1; /// score.0 += 1;
/// } /// }
/// } /// }
/// # update_score_system.system(); /// # bevy_ecs::system::assert_is_system(update_score_system);
/// ``` /// ```
#[inline] #[inline]
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {

View File

@ -130,8 +130,8 @@ where
SystemB: IntoSystem<Payload, Out, ParamB>, SystemB: IntoSystem<Payload, Out, ParamB>,
{ {
fn chain(self, system: SystemB) -> ChainSystem<SystemA::System, SystemB::System> { fn chain(self, system: SystemB) -> ChainSystem<SystemA::System, SystemB::System> {
let system_a = self.system(); let system_a = IntoSystem::into_system(self);
let system_b = system.system(); let system_b = IntoSystem::into_system(system);
ChainSystem { ChainSystem {
name: Cow::Owned(format!("Chain({}, {})", system_a.name(), system_b.name())), name: Cow::Owned(format!("Chain({}, {})", system_a.name(), system_b.name())),
system_a, system_a,

View File

@ -43,7 +43,7 @@ use std::{
/// // Access the resource through `param.foo` /// // Access the resource through `param.foo`
/// } /// }
/// ///
/// # my_system.system(); /// # bevy_ecs::system::assert_is_system(my_system);
/// ``` /// ```
pub trait SystemParam: Sized { pub trait SystemParam: Sized {
type Fetch: for<'w, 's> SystemParamFetch<'w, 's>; type Fetch: for<'w, 's> SystemParamFetch<'w, 's>;
@ -614,8 +614,8 @@ impl<'w, 's> SystemParamFetch<'w, 's> for WorldState {
/// fn read_from_local(local: Local<usize>) -> usize { /// fn read_from_local(local: Local<usize>) -> usize {
/// *local /// *local
/// } /// }
/// let mut write_system = write_to_local.system(); /// let mut write_system = IntoSystem::into_system(write_to_local);
/// let mut read_system = read_from_local.system(); /// let mut read_system = IntoSystem::into_system(read_from_local);
/// write_system.initialize(world); /// write_system.initialize(world);
/// read_system.initialize(world); /// read_system.initialize(world);
/// ///
@ -718,7 +718,7 @@ impl<'w, 's, T: Resource + FromWorld> SystemParamFetch<'w, 's> for LocalState<T>
/// removed.iter().for_each(|removed_entity| println!("{:?}", removed_entity)); /// removed.iter().for_each(|removed_entity| println!("{:?}", removed_entity));
/// } /// }
/// ///
/// # react_on_removal.system(); /// # bevy_ecs::system::assert_is_system(react_on_removal);
/// ``` /// ```
pub struct RemovedComponents<'a, T: Component> { pub struct RemovedComponents<'a, T: Component> {
world: &'a World, world: &'a World,

View File

@ -65,10 +65,7 @@ impl<C: Component + AsStd140 + Clone> Plugin for UniformComponentPlugin<C> {
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) { if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
render_app render_app
.insert_resource(ComponentUniforms::<C>::default()) .insert_resource(ComponentUniforms::<C>::default())
.add_system_to_stage( .add_system_to_stage(RenderStage::Prepare, prepare_uniform_components::<C>);
RenderStage::Prepare,
prepare_uniform_components::<C>.system(),
);
} }
} }
} }

View File

@ -87,7 +87,10 @@ fn main() {
// Here we create a _not done_ criteria by piping the output of // Here we create a _not done_ criteria by piping the output of
// the `is_done` system and inverting the output. // the `is_done` system and inverting the output.
// Notice a string literal also works as a label. // Notice a string literal also works as a label.
.with_run_criteria(RunCriteria::pipe("is_done_label", inverse.system())) .with_run_criteria(RunCriteria::pipe(
"is_done_label",
IntoSystem::into_system(inverse),
))
// `collision` and `sfx` are not ordered with respect to // `collision` and `sfx` are not ordered with respect to
// each other, and may run in any order // each other, and may run in any order
.with_system(collision) .with_system(collision)