From 406dd470bbdc36efc26714163199f33ad148adc5 Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Tue, 17 May 2022 13:18:28 +0300 Subject: [PATCH 01/19] fix assets tracking logic --- src/asset.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/asset.rs b/src/asset.rs index da905b7..40c286b 100644 --- a/src/asset.rs +++ b/src/asset.rs @@ -45,7 +45,8 @@ pub(crate) fn assets_progress( // TODO: avoid this temporary vec (HashSet::drain_filter is in Rust nightly) let mut done = vec![]; for handle in loading.handles.iter() { - if server.get_load_state(*handle) != LoadState::Loading { + let loadstate = server.get_load_state(*handle); + if loadstate == LoadState::Loaded || loadstate == LoadState::Failed { done.push(*handle); } } From 4db05769c1c30a6aebc4d8e8ca5ac25c146c5e05 Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Sat, 23 Apr 2022 00:08:19 +0300 Subject: [PATCH 02/19] depend on bevy main --- Cargo.toml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c2b1d09..387a3f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,14 +10,14 @@ categories = ["game-engines"] description = "Bevy plugin to help implement loading states" [dependencies] -bevy_ecs = "0.7" -bevy_app = "0.7" -bevy_asset = { version = "0.7", optional = true } -bevy_utils = { version = "0.7", optional = true } +bevy_ecs = { git = "https://github.com/bevyengine/bevy" } +bevy_app = { git = "https://github.com/bevyengine/bevy" } +bevy_asset = { git = "https://github.com/bevyengine/bevy", optional = true } +bevy_utils = { git = "https://github.com/bevyengine/bevy", optional = true } [dependencies.iyes_loopless] -version = "0.5" -# path = "../iyes_loopless/" +git = "https://github.com/IyesGames/iyes_loopless" +branch = "bevy_main" optional = true default-features = false features = ["states", "app"] @@ -26,9 +26,8 @@ features = ["states", "app"] assets = ["bevy_asset", "bevy_utils"] [dev-dependencies] -bevy = "0.7" -iyes_loopless = "0.5" -# iyes_loopless = {path = "../iyes_loopless/"} +bevy = { git = "https://github.com/bevyengine/bevy" } +iyes_loopless = { git = "https://github.com/IyesGames/iyes_loopless", branch = "bevy_main" } [[example]] name = "full" From 47d57124d096ba7ac04e3fdbc68aba241092e103 Mon Sep 17 00:00:00 2001 From: Niklas Eicker Date: Fri, 29 Jul 2022 21:45:42 +0700 Subject: [PATCH 03/19] Udate to latest Bevy main; prep for 0.8 (#16) * Update to latest Bevy commit * Manually derive StageLabel * Do not pin the Bevy commit * Cargo.toml: point back at non-forked iyes_loopless Co-authored-by: Ida Iyes <40234599+inodentry@users.noreply.github.com> --- examples/full.rs | 5 +++-- src/asset.rs | 2 +- src/lib.rs | 54 +++++++++++++++++++++++++----------------------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/examples/full.rs b/examples/full.rs index cb19f27..68eab1d 100644 --- a/examples/full.rs +++ b/examples/full.rs @@ -22,7 +22,8 @@ fn main() { .add_plugin( ProgressPlugin::new(AppState::Splash) .continue_to(AppState::MainMenu) - .track_assets()) + .track_assets(), + ) // Add plugin for our game loading screen .add_plugin(ProgressPlugin::new(AppState::GameLoading).continue_to(AppState::InGame)) // Load our UI assets during our splash screen @@ -37,7 +38,7 @@ fn main() { // we can also add regular untracked systems to our loading screen, // like to draw our progress bar: .with_system(ui_progress_bar) - .into() + .into(), ) .run(); } diff --git a/src/asset.rs b/src/asset.rs index 40c286b..896f021 100644 --- a/src/asset.rs +++ b/src/asset.rs @@ -1,6 +1,6 @@ +use bevy_asset::prelude::*; use bevy_asset::HandleId; use bevy_asset::LoadState; -use bevy_asset::prelude::*; use bevy_ecs::prelude::*; use bevy_utils::HashSet; diff --git a/src/lib.rs b/src/lib.rs index c83ef45..dbf6193 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,21 +47,21 @@ use std::ops::{Add, AddAssign}; use std::sync::atomic::AtomicU32; use std::sync::atomic::Ordering as MemOrdering; -use bevy_ecs::schedule::StateData; -use bevy_ecs::prelude::*; use bevy_app::prelude::*; +use bevy_ecs::prelude::*; +use bevy_ecs::schedule::StateData; #[cfg(feature = "assets")] mod asset; /// Most used imports pub mod prelude { - pub use crate::ProgressPlugin; - pub use crate::Progress; - pub use crate::ProgressSystem; - pub use crate::ProgressCounter; #[cfg(feature = "assets")] pub use crate::asset::AssetsLoading; + pub use crate::Progress; + pub use crate::ProgressCounter; + pub use crate::ProgressPlugin; + pub use crate::ProgressSystem; } /// Progress reported by a system @@ -146,10 +146,10 @@ impl AddAssign for Progress { /// /// ```rust /// # use bevy::prelude::*; -/// # use bevy_loading::ProgressPlugin; +/// # use iyes_progress::ProgressPlugin; /// # let mut app = App::default(); -/// app.add_plugin(LoadingPlugin::new(MyState::GameLoading).continue_to(MyState::InGame)); -/// app.add_plugin(LoadingPlugin::new(MyState::Splash).continue_to(MyState::MainMenu)); +/// app.add_plugin(ProgressPlugin::new(MyState::GameLoading).continue_to(MyState::InGame)); +/// app.add_plugin(ProgressPlugin::new(MyState::Splash).continue_to(MyState::MainMenu)); /// # #[derive(Debug, Clone, PartialEq, Eq, Hash)] /// # enum MyState { /// # Splash, @@ -195,10 +195,7 @@ impl ProgressPlugin { #[cfg(not(feature = "iyes_loopless"))] impl Plugin for ProgressPlugin { fn build(&self, app: &mut App) { - app.add_system_set( - SystemSet::on_enter(self.state.clone()) - .with_system(loadstate_enter), - ); + app.add_system_set(SystemSet::on_enter(self.state.clone()).with_system(loadstate_enter)); app.add_system_set( SystemSet::on_update(self.state.clone()) .with_system( @@ -212,12 +209,9 @@ impl Plugin for ProgressPlugin { .exclusive_system() .at_end() .label(ProgressSystemLabel::CheckProgress), - ) - ); - app.add_system_set( - SystemSet::on_exit(self.state.clone()) - .with_system(loadstate_exit) + ), ); + app.add_system_set(SystemSet::on_exit(self.state.clone()).with_system(loadstate_exit)); #[cfg(feature = "assets")] if self.track_assets { @@ -227,8 +221,7 @@ impl Plugin for ProgressPlugin { .with_system(asset::assets_progress.track_progress()), ); app.add_system_set( - SystemSet::on_exit(self.state.clone()) - .with_system(asset::assets_loading_reset), + SystemSet::on_exit(self.state.clone()).with_system(asset::assets_loading_reset), ); } @@ -242,20 +235,27 @@ impl Plugin for ProgressPlugin { #[cfg(feature = "iyes_loopless")] impl Plugin for ProgressPlugin { fn build(&self, app: &mut App) { - use iyes_loopless::prelude::*; use iyes_loopless::condition::IntoConditionalExclusiveSystem; + use iyes_loopless::prelude::*; app.add_enter_system(self.state.clone(), loadstate_enter); app.add_exit_system(self.state.clone(), loadstate_exit); - #[derive(Debug, Clone, PartialEq, Eq, Hash, StageLabel)] + #[derive(Debug, Clone)] struct StageLabel(String); + + impl bevy_ecs::schedule::StageLabel for StageLabel { + fn as_str(&self) -> &'static str { + Box::leak(self.0.clone().into_boxed_str()) + } + } + let stagelabel = StageLabel(format!("iyes_progress init: {:?}", &self.state)); app.add_stage_after( iyes_loopless::state::app::StateTransitionStageLabel::from_type::(), stagelabel.clone(), - SystemStage::single_threaded() + SystemStage::single_threaded(), ); app.add_system_to_stage( @@ -281,7 +281,7 @@ impl Plugin for ProgressPlugin { app.add_system( asset::assets_progress .track_progress() - .run_in_state(self.state.clone()) + .run_in_state(self.state.clone()), ); } @@ -303,7 +303,8 @@ pub trait ProgressSystem: IntoSystem<(), Progress, Params> { #[cfg(not(feature = "iyes_loopless"))] impl ProgressSystem for S -where S: IntoSystem<(), Progress, Params> +where + S: IntoSystem<(), Progress, Params>, { fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor { self.chain( @@ -326,7 +327,8 @@ pub trait ProgressSystem: IntoSystem<(), Progress, Params> { #[cfg(feature = "iyes_loopless")] impl ProgressSystem for S -where S: IntoSystem<(), Progress, Params> +where + S: IntoSystem<(), Progress, Params>, { fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor { use iyes_loopless::condition::IntoConditionalSystem; From 09eaadc3a4947a119ef56e78ce19587a881ea14f Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Fri, 29 Jul 2022 18:17:41 +0300 Subject: [PATCH 04/19] loopless moved some things around --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index dbf6193..0a211d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -253,7 +253,7 @@ impl Plugin for ProgressPlugin { let stagelabel = StageLabel(format!("iyes_progress init: {:?}", &self.state)); app.add_stage_after( - iyes_loopless::state::app::StateTransitionStageLabel::from_type::(), + iyes_loopless::state::StateTransitionStageLabel::from_type::(), stagelabel.clone(), SystemStage::single_threaded(), ); From d0de750f13ac895d097acf2eacbee1835dcfd7cd Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Mon, 1 Aug 2022 01:22:51 +0300 Subject: [PATCH 05/19] v0.4: Bevy 0.8 --- Cargo.toml | 17 ++++++++--------- README.md | 4 +++- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 387a3f5..4c36ebc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iyes_progress" -version = "0.3.0" +version = "0.4.0" edition = "2021" license = "MIT OR Apache-2.0" readme = "README.md" @@ -10,14 +10,13 @@ categories = ["game-engines"] description = "Bevy plugin to help implement loading states" [dependencies] -bevy_ecs = { git = "https://github.com/bevyengine/bevy" } -bevy_app = { git = "https://github.com/bevyengine/bevy" } -bevy_asset = { git = "https://github.com/bevyengine/bevy", optional = true } -bevy_utils = { git = "https://github.com/bevyengine/bevy", optional = true } +bevy_ecs = "0.8" +bevy_app = "0.8" +bevy_asset = { version = "0.8", optional = true } +bevy_utils = { version = "0.8", optional = true } [dependencies.iyes_loopless] -git = "https://github.com/IyesGames/iyes_loopless" -branch = "bevy_main" +version = "0.7" optional = true default-features = false features = ["states", "app"] @@ -26,8 +25,8 @@ features = ["states", "app"] assets = ["bevy_asset", "bevy_utils"] [dev-dependencies] -bevy = { git = "https://github.com/bevyengine/bevy" } -iyes_loopless = { git = "https://github.com/IyesGames/iyes_loopless", branch = "bevy_main" } +bevy = "0.8" +iyes_loopless = "0.7" [[example]] name = "full" diff --git a/README.md b/README.md index 3e69cf7..a8f9a7e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,9 @@ Bevy Compatibility: | Bevy Version | Plugin Version | |--------------|----------------------| | `main` | `bevy_main` | -| `0.7` | `0.3`, `main` | +| `0.8` | `main` | +| `0.8` | `0.4` | +| `0.7` | `0.3`, | | `0.6` | `bevy_loading = 0.2` | | `0.5` | `bevy_loading = 0.1` | From b3b6aacc6a713b273e254de7db7fe73ed0fe97a7 Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Fri, 12 Aug 2022 23:43:16 +0300 Subject: [PATCH 06/19] refactor things conditional on loopless into separate files --- src/legacy.rs | 84 ++++++++++++++++++++++ src/lib.rs | 184 +++--------------------------------------------- src/loopless.rs | 105 +++++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 176 deletions(-) create mode 100644 src/legacy.rs create mode 100644 src/loopless.rs diff --git a/src/legacy.rs b/src/legacy.rs new file mode 100644 index 0000000..9494cd1 --- /dev/null +++ b/src/legacy.rs @@ -0,0 +1,84 @@ +use bevy_app::prelude::*; +use bevy_ecs::prelude::*; +use bevy_ecs::schedule::StateData; + +use crate::{ProgressPlugin, ProgressSystemLabel}; +use crate::ProgressCounter; +use crate::Progress; + +pub mod prelude { + pub use super::ProgressSystem; +} + +impl Plugin for ProgressPlugin { + fn build(&self, app: &mut App) { + app.add_system_set(SystemSet::on_enter(self.state.clone()).with_system(crate::loadstate_enter)); + app.add_system_set( + SystemSet::on_update(self.state.clone()) + .with_system( + crate::next_frame + .exclusive_system() + .at_start() + .label(ProgressSystemLabel::Preparation), + ) + .with_system( + check_progress::(self.next_state.clone()) + .exclusive_system() + .at_end() + .label(ProgressSystemLabel::CheckProgress), + ), + ); + app.add_system_set(SystemSet::on_exit(self.state.clone()).with_system(crate::loadstate_exit)); + + #[cfg(feature = "assets")] + if self.track_assets { + app.init_resource::(); + app.add_system_set( + SystemSet::on_update(self.state.clone()) + .with_system(crate::asset::assets_progress.track_progress()), + ); + app.add_system_set( + SystemSet::on_exit(self.state.clone()).with_system(crate::asset::assets_loading_reset), + ); + } + + #[cfg(not(feature = "assets"))] + if self.track_assets { + panic!("Enable the \"assets\" cargo feature to use assets tracking!"); + } + } +} + +/// Extension trait for systems with Progress tracking +pub trait ProgressSystem: IntoSystem<(), Progress, Params> { + /// Call this to add your system returning [`Progress`] to your [`App`] + /// + /// This adds the functionality for tracking the returned Progress. + fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor; +} + +impl ProgressSystem for S +where + S: IntoSystem<(), Progress, Params>, +{ + fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor { + self.chain( + |In(progress): In, counter: Res| { + counter.manually_track(progress); + }, + ) + .label(ProgressSystemLabel::Tracking) + } +} + +fn check_progress(next_state: Option) -> impl FnMut(&mut World) { + move |world| { + let progress = world.resource::().progress_complete(); + if progress.is_ready() { + if let Some(next_state) = &next_state { + let mut state = world.resource_mut::>(); + state.set(next_state.clone()).ok(); + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 0a211d1..5a9ecd7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,12 +47,15 @@ use std::ops::{Add, AddAssign}; use std::sync::atomic::AtomicU32; use std::sync::atomic::Ordering as MemOrdering; -use bevy_app::prelude::*; use bevy_ecs::prelude::*; use bevy_ecs::schedule::StateData; #[cfg(feature = "assets")] mod asset; +#[cfg(feature = "iyes_loopless")] +mod loopless; +#[cfg(not(feature = "iyes_loopless"))] +mod legacy; /// Most used imports pub mod prelude { @@ -61,7 +64,10 @@ pub mod prelude { pub use crate::Progress; pub use crate::ProgressCounter; pub use crate::ProgressPlugin; - pub use crate::ProgressSystem; + #[cfg(feature = "iyes_loopless")] + pub use crate::loopless::prelude::*; + #[cfg(not(feature = "iyes_loopless"))] + pub use crate::legacy::prelude::*; } /// Progress reported by a system @@ -192,156 +198,6 @@ impl ProgressPlugin { } } -#[cfg(not(feature = "iyes_loopless"))] -impl Plugin for ProgressPlugin { - fn build(&self, app: &mut App) { - app.add_system_set(SystemSet::on_enter(self.state.clone()).with_system(loadstate_enter)); - app.add_system_set( - SystemSet::on_update(self.state.clone()) - .with_system( - next_frame - .exclusive_system() - .at_start() - .label(ProgressSystemLabel::Preparation), - ) - .with_system( - check_progress::(self.next_state.clone()) - .exclusive_system() - .at_end() - .label(ProgressSystemLabel::CheckProgress), - ), - ); - app.add_system_set(SystemSet::on_exit(self.state.clone()).with_system(loadstate_exit)); - - #[cfg(feature = "assets")] - if self.track_assets { - app.init_resource::(); - app.add_system_set( - SystemSet::on_update(self.state.clone()) - .with_system(asset::assets_progress.track_progress()), - ); - app.add_system_set( - SystemSet::on_exit(self.state.clone()).with_system(asset::assets_loading_reset), - ); - } - - #[cfg(not(feature = "assets"))] - if self.track_assets { - panic!("Enable the \"assets\" cargo feature to use assets tracking!"); - } - } -} - -#[cfg(feature = "iyes_loopless")] -impl Plugin for ProgressPlugin { - fn build(&self, app: &mut App) { - use iyes_loopless::condition::IntoConditionalExclusiveSystem; - use iyes_loopless::prelude::*; - - app.add_enter_system(self.state.clone(), loadstate_enter); - app.add_exit_system(self.state.clone(), loadstate_exit); - - #[derive(Debug, Clone)] - struct StageLabel(String); - - impl bevy_ecs::schedule::StageLabel for StageLabel { - fn as_str(&self) -> &'static str { - Box::leak(self.0.clone().into_boxed_str()) - } - } - - let stagelabel = StageLabel(format!("iyes_progress init: {:?}", &self.state)); - - app.add_stage_after( - iyes_loopless::state::StateTransitionStageLabel::from_type::(), - stagelabel.clone(), - SystemStage::single_threaded(), - ); - - app.add_system_to_stage( - stagelabel, - next_frame - .run_in_state(self.state.clone()) - .at_start() - .label(ProgressSystemLabel::Preparation), - ); - - app.add_system_to_stage( - CoreStage::Last, - check_progress::(self.next_state.clone()) - .run_in_state(self.state.clone()) - .at_end() - .label(ProgressSystemLabel::CheckProgress), - ); - - #[cfg(feature = "assets")] - if self.track_assets { - app.init_resource::(); - app.add_exit_system(self.state.clone(), asset::assets_loading_reset); - app.add_system( - asset::assets_progress - .track_progress() - .run_in_state(self.state.clone()), - ); - } - - #[cfg(not(feature = "assets"))] - if self.track_assets { - panic!("Enable the \"assets\" cargo feature to use assets tracking!"); - } - } -} - -#[cfg(not(feature = "iyes_loopless"))] -/// Extension trait for systems with Progress tracking -pub trait ProgressSystem: IntoSystem<(), Progress, Params> { - /// Call this to add your system returning [`Progress`] to your [`App`] - /// - /// This adds the functionality for tracking the returned Progress. - fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor; -} - -#[cfg(not(feature = "iyes_loopless"))] -impl ProgressSystem for S -where - S: IntoSystem<(), Progress, Params>, -{ - fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor { - self.chain( - |In(progress): In, counter: Res| { - counter.manually_track(progress) - }, - ) - .label(ProgressSystemLabel::Tracking) - } -} - -#[cfg(feature = "iyes_loopless")] -/// Extension trait for systems with Progress tracking -pub trait ProgressSystem: IntoSystem<(), Progress, Params> { - /// Call this to add your system returning [`Progress`] to your [`App`] - /// - /// This adds the functionality for tracking the returned Progress. - fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor; -} - -#[cfg(feature = "iyes_loopless")] -impl ProgressSystem for S -where - S: IntoSystem<(), Progress, Params>, -{ - fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor { - use iyes_loopless::condition::IntoConditionalSystem; - self.chain( - |In(progress): In, counter: Res| { - counter.manually_track(progress) - }, - ) - .into_conditional() - .label(ProgressSystemLabel::Tracking) - } -} - /// Label to control system execution order #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, SystemLabel)] pub enum ProgressSystemLabel { @@ -416,30 +272,6 @@ fn loadstate_exit(mut commands: Commands) { commands.remove_resource::(); } -#[cfg(not(feature = "iyes_loopless"))] -fn check_progress(next_state: Option) -> impl FnMut(&mut World) { - move |world| { - let progress = world.resource::().progress(); - if progress.is_ready() { - if let Some(next_state) = &next_state { - let mut state = world.resource_mut::>(); - state.set(next_state.clone()).ok(); - } - } - } -} -#[cfg(feature = "iyes_loopless")] -fn check_progress(next_state: Option) -> impl FnMut(&mut World) { - move |world| { - let progress = world.resource::().progress(); - if progress.is_ready() { - if let Some(next_state) = &next_state { - world.insert_resource(iyes_loopless::state::NextState(next_state.clone())); - } - } - } -} - fn next_frame(world: &mut World) { let counter = world.resource::(); diff --git a/src/loopless.rs b/src/loopless.rs new file mode 100644 index 0000000..e481977 --- /dev/null +++ b/src/loopless.rs @@ -0,0 +1,105 @@ +use bevy_app::prelude::*; +use bevy_ecs::prelude::*; +use bevy_ecs::schedule::StateData; + +use crate::{ProgressPlugin, ProgressSystemLabel}; +use crate::ProgressCounter; +use crate::Progress; + +pub mod prelude { + pub use super::ProgressSystem; +} + +impl Plugin for ProgressPlugin { + fn build(&self, app: &mut App) { + use iyes_loopless::condition::IntoConditionalExclusiveSystem; + use iyes_loopless::prelude::*; + + app.add_enter_system(self.state.clone(), crate::loadstate_enter); + app.add_exit_system(self.state.clone(), crate::loadstate_exit); + + #[derive(Debug, Clone)] + struct StageLabel(String); + + impl bevy_ecs::schedule::StageLabel for StageLabel { + fn as_str(&self) -> &'static str { + Box::leak(self.0.clone().into_boxed_str()) + } + } + + let stagelabel = StageLabel(format!("iyes_progress init: {:?}", &self.state)); + + app.add_stage_after( + iyes_loopless::state::StateTransitionStageLabel::from_type::(), + stagelabel.clone(), + SystemStage::single_threaded(), + ); + + app.add_system_to_stage( + stagelabel, + crate::next_frame + .run_in_state(self.state.clone()) + .at_start() + .label(ProgressSystemLabel::Preparation), + ); + + app.add_system_to_stage( + CoreStage::Last, + check_progress::(self.next_state.clone()) + .run_in_state(self.state.clone()) + .at_end() + .label(ProgressSystemLabel::CheckProgress), + ); + + #[cfg(feature = "assets")] + if self.track_assets { + app.init_resource::(); + app.add_exit_system(self.state.clone(), crate::asset::assets_loading_reset); + app.add_system( + crate::asset::assets_progress + .track_progress() + .run_in_state(self.state.clone()), + ); + } + + #[cfg(not(feature = "assets"))] + if self.track_assets { + panic!("Enable the \"assets\" cargo feature to use assets tracking!"); + } + } +} + +/// Extension trait for systems with Progress tracking +pub trait ProgressSystem: IntoSystem<(), Progress, Params> { + /// Call this to add your system returning [`Progress`] to your [`App`] + /// + /// This adds the functionality for tracking the returned Progress. + fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor; +} + +impl ProgressSystem for S +where + S: IntoSystem<(), Progress, Params>, +{ + fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor { + use iyes_loopless::condition::IntoConditionalSystem; + self.chain( + |In(progress): In, counter: Res| { + counter.manually_track(progress); + }, + ) + .into_conditional() + .label(ProgressSystemLabel::Tracking) + } +} + +fn check_progress(next_state: Option) -> impl FnMut(&mut World) { + move |world| { + let progress = world.resource::().progress_complete(); + if progress.is_ready() { + if let Some(next_state) = &next_state { + world.insert_resource(iyes_loopless::state::NextState(next_state.clone())); + } + } + } +} From 80623a1e4a286a6edd54350d57e34e48b0aee5d1 Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Fri, 12 Aug 2022 23:44:36 +0300 Subject: [PATCH 07/19] implement "hidden progress" --- src/legacy.rs | 49 ++++++++++++++++++++++++++++-- src/lib.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++++++- src/loopless.rs | 53 +++++++++++++++++++++++++++++++-- 3 files changed, 176 insertions(+), 5 deletions(-) diff --git a/src/legacy.rs b/src/legacy.rs index 9494cd1..9f0dda7 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -4,10 +4,10 @@ use bevy_ecs::schedule::StateData; use crate::{ProgressPlugin, ProgressSystemLabel}; use crate::ProgressCounter; -use crate::Progress; +use crate::{Progress, HiddenProgress}; pub mod prelude { - pub use super::ProgressSystem; + pub use super::{ProgressSystem, HiddenProgressSystem, MixedProgressSystem}; } impl Plugin for ProgressPlugin { @@ -71,6 +71,51 @@ where } } +/// Extension trait for systems with Progress tracking +pub trait HiddenProgressSystem: IntoSystem<(), HiddenProgress, Params> { + /// Call this to add your system returning [`HiddenProgress`] to your [`App`] + /// + /// This adds the functionality for tracking the returned Progress. + fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor; +} + +impl HiddenProgressSystem for S +where + S: IntoSystem<(), HiddenProgress, Params>, +{ + fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor { + self.chain( + |In(progress): In, counter: Res| { + counter.manually_track_hidden(progress); + }, + ) + .label(ProgressSystemLabel::Tracking) + } +} + +/// Extension trait for systems with Progress tracking +pub trait MixedProgressSystem: IntoSystem<(), (Progress, HiddenProgress), Params> { + /// Call this to add your system returning both `Progress` and `HiddenProgress` to your [`App`] + /// + /// This adds the functionality for tracking the returned Progress. + fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor; +} + +impl MixedProgressSystem for S +where + S: IntoSystem<(), (Progress, HiddenProgress), Params>, +{ + fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor { + self.chain( + |In((progress, hidden)): In<(Progress, HiddenProgress)>, counter: Res| { + counter.manually_track(progress); + counter.manually_track_hidden(hidden); + }, + ) + .label(ProgressSystemLabel::Tracking) + } +} + fn check_progress(next_state: Option) -> impl FnMut(&mut World) { move |world| { let progress = world.resource::().progress_complete(); diff --git a/src/lib.rs b/src/lib.rs index 5a9ecd7..2a16709 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,6 +62,7 @@ pub mod prelude { #[cfg(feature = "assets")] pub use crate::asset::AssetsLoading; pub use crate::Progress; + pub use crate::HiddenProgress; pub use crate::ProgressCounter; pub use crate::ProgressPlugin; #[cfg(feature = "iyes_loopless")] @@ -79,6 +80,10 @@ pub mod prelude { /// /// For your convenience, you can easily convert `bool`s into this type. /// You can also convert `Progress` values into floats in the 0.0..1.0 range. +/// +/// If you want your system to report some progress in a way that is counted separately +/// and should not affect progress bars or other user-facing indicators, you can +/// use [`HiddenProgress`] instead. #[derive(Debug, Clone, Copy, Default)] pub struct Progress { /// Units of work completed during this execution of the system @@ -132,6 +137,18 @@ impl AddAssign for Progress { } } +/// "Hidden" progress reported by a system. +/// +/// Works just like the regular [`Progress`], but will be accounted differently +/// in [`ProgressCounter`]. +/// +/// Hidden progress counts towards the true total (like for triggering the +/// state transition) as reported by the `progress_complete` method, but is not +/// counted by the `progress` method. The intention is that it should not +/// affect things like progress bars and other user-facing indicators. +#[derive(Debug, Clone, Copy, Default)] +pub struct HiddenProgress(pub Progress); + /// Add this plugin to your app, to use this crate for the specified state. /// /// If you have multiple different states that need progress tracking, @@ -229,7 +246,10 @@ pub struct ProgressCounter { // allowing them to run in parallel done: AtomicU32, total: AtomicU32, + done_hidden: AtomicU32, + total_hidden: AtomicU32, persisted: Progress, + persisted_hidden: Progress, } impl ProgressCounter { @@ -238,7 +258,13 @@ impl ProgressCounter { /// This is the combined total of all systems. /// /// To get correct information, make sure that you call this function only after - /// all your systems that track progress finished + /// all your systems that track progress finished. + /// + /// This does not include "hidden" progress. To get the full "real" total, use + /// `progress_complete`. + /// + /// Use this method for progress bars and other things that indicate/report + /// progress information to the user. pub fn progress(&self) -> Progress { let total = self.total.load(MemOrdering::Acquire); let done = self.done.load(MemOrdering::Acquire); @@ -246,6 +272,28 @@ impl ProgressCounter { Progress { done, total } } + /// Get the latest overall progress information + /// + /// This is the combined total of all systems. + /// + /// To get correct information, make sure that you call this function only after + /// all your systems that track progress finished + /// + /// This includes "hidden" progress. To get only the "visible" progress, use + /// `progress`. + /// + /// This is the method to be used for things like state transitions, and other + /// use cases that must account for the "true" actual progress of the + /// registered systems. + pub fn progress_complete(&self) -> Progress { + let total = self.total.load(MemOrdering::Acquire) + + self.total_hidden.load(MemOrdering::Acquire); + let done = self.done.load(MemOrdering::Acquire) + + self.done_hidden.load(MemOrdering::Acquire); + + Progress { done, total } + } + /// Add some amount of progress to the running total for the current frame. /// /// In most cases you do not want to call this function yourself. @@ -257,11 +305,33 @@ impl ProgressCounter { .fetch_add(progress.done.min(progress.total), MemOrdering::Release); } + /// Add some amount of "hidden" progress to the running total for the current frame. + /// + /// Hidden progress counts towards the true total (like for triggering the + /// state transition) as reported by the `progress_complete` method, but is not + /// counted by the `progress` method. The intention is that it should not + /// affect things like progress bars and other user-facing indicators. + /// + /// In most cases you do not want to call this function yourself. + /// Let your systems return a [`Progress`] and wrap them in [`track`] instead. + pub fn manually_track_hidden(&self, progress: HiddenProgress) { + self.total_hidden.fetch_add(progress.0.total, MemOrdering::Release); + // use `min` to clamp in case a bad user provides `done > total` + self.done_hidden + .fetch_add(progress.0.done.min(progress.0.total), MemOrdering::Release); + } + /// Persist progress for the rest of the current state pub fn persist_progress(&mut self, progress: Progress) { self.manually_track(progress); self.persisted += progress; } + + /// Persist hidden progress for the rest of the current state + pub fn persist_progress_hidden(&mut self, progress: HiddenProgress) { + self.manually_track_hidden(progress); + self.persisted_hidden += progress.0; + } } fn loadstate_enter(mut commands: Commands) { @@ -281,4 +351,11 @@ fn next_frame(world: &mut World) { counter .total .store(counter.persisted.total, MemOrdering::Release); + + counter + .done_hidden + .store(counter.persisted_hidden.done, MemOrdering::Release); + counter + .total_hidden + .store(counter.persisted_hidden.total, MemOrdering::Release); } diff --git a/src/loopless.rs b/src/loopless.rs index e481977..dccd1dc 100644 --- a/src/loopless.rs +++ b/src/loopless.rs @@ -4,10 +4,10 @@ use bevy_ecs::schedule::StateData; use crate::{ProgressPlugin, ProgressSystemLabel}; use crate::ProgressCounter; -use crate::Progress; +use crate::{Progress, HiddenProgress}; pub mod prelude { - pub use super::ProgressSystem; + pub use super::{ProgressSystem, HiddenProgressSystem, MixedProgressSystem}; } impl Plugin for ProgressPlugin { @@ -93,6 +93,55 @@ where } } +/// Extension trait for systems with Progress tracking +pub trait HiddenProgressSystem: IntoSystem<(), HiddenProgress, Params> { + /// Call this to add your system returning [`HiddenProgress`] to your [`App`] + /// + /// This adds the functionality for tracking the returned Progress. + fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor; +} + +impl HiddenProgressSystem for S +where + S: IntoSystem<(), HiddenProgress, Params>, +{ + fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor { + use iyes_loopless::condition::IntoConditionalSystem; + self.chain( + |In(progress): In, counter: Res| { + counter.manually_track_hidden(progress); + }, + ) + .into_conditional() + .label(ProgressSystemLabel::Tracking) + } +} + +/// Extension trait for systems with Progress tracking +pub trait MixedProgressSystem: IntoSystem<(), (Progress, HiddenProgress), Params> { + /// Call this to add your system returning both `Progress` and `HiddenProgress` to your [`App`] + /// + /// This adds the functionality for tracking the returned Progress. + fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor; +} + +impl MixedProgressSystem for S +where + S: IntoSystem<(), (Progress, HiddenProgress), Params>, +{ + fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor { + use iyes_loopless::condition::IntoConditionalSystem; + self.chain( + |In((progress, hidden)): In<(Progress, HiddenProgress)>, counter: Res| { + counter.manually_track(progress); + counter.manually_track_hidden(hidden); + }, + ) + .into_conditional() + .label(ProgressSystemLabel::Tracking) + } +} + fn check_progress(next_state: Option) -> impl FnMut(&mut World) { move |world| { let progress = world.resource::().progress_complete(); From 0d188fb9caaf859dacd77dcdfec551c80a053710 Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Sat, 13 Aug 2022 01:15:46 +0300 Subject: [PATCH 08/19] abstract progress return types with a trait --- src/legacy.rs | 62 +++++++---------------------------------------- src/lib.rs | 30 +++++++++++++++++++++++ src/loopless.rs | 64 +++++++------------------------------------------ 3 files changed, 47 insertions(+), 109 deletions(-) diff --git a/src/legacy.rs b/src/legacy.rs index 9f0dda7..5bf91c8 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -4,10 +4,10 @@ use bevy_ecs::schedule::StateData; use crate::{ProgressPlugin, ProgressSystemLabel}; use crate::ProgressCounter; -use crate::{Progress, HiddenProgress}; +use crate::ApplyProgress; pub mod prelude { - pub use super::{ProgressSystem, HiddenProgressSystem, MixedProgressSystem}; + pub use super::ProgressSystem; } impl Plugin for ProgressPlugin { @@ -49,67 +49,23 @@ impl Plugin for ProgressPlugin { } } -/// Extension trait for systems with Progress tracking -pub trait ProgressSystem: IntoSystem<(), Progress, Params> { +/// Extension trait for systems with progress tracking +pub trait ProgressSystem: IntoSystem<(), T, Params> { /// Call this to add your system returning [`Progress`] to your [`App`] /// /// This adds the functionality for tracking the returned Progress. fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor; } -impl ProgressSystem for S +impl ProgressSystem for S where - S: IntoSystem<(), Progress, Params>, + T: ApplyProgress + 'static, + S: IntoSystem<(), T, Params>, { fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor { self.chain( - |In(progress): In, counter: Res| { - counter.manually_track(progress); - }, - ) - .label(ProgressSystemLabel::Tracking) - } -} - -/// Extension trait for systems with Progress tracking -pub trait HiddenProgressSystem: IntoSystem<(), HiddenProgress, Params> { - /// Call this to add your system returning [`HiddenProgress`] to your [`App`] - /// - /// This adds the functionality for tracking the returned Progress. - fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor; -} - -impl HiddenProgressSystem for S -where - S: IntoSystem<(), HiddenProgress, Params>, -{ - fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor { - self.chain( - |In(progress): In, counter: Res| { - counter.manually_track_hidden(progress); - }, - ) - .label(ProgressSystemLabel::Tracking) - } -} - -/// Extension trait for systems with Progress tracking -pub trait MixedProgressSystem: IntoSystem<(), (Progress, HiddenProgress), Params> { - /// Call this to add your system returning both `Progress` and `HiddenProgress` to your [`App`] - /// - /// This adds the functionality for tracking the returned Progress. - fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor; -} - -impl MixedProgressSystem for S -where - S: IntoSystem<(), (Progress, HiddenProgress), Params>, -{ - fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor { - self.chain( - |In((progress, hidden)): In<(Progress, HiddenProgress)>, counter: Res| { - counter.manually_track(progress); - counter.manually_track_hidden(hidden); + |In(progress): In, counter: Res| { + progress.apply_progress(&*counter); }, ) .label(ProgressSystemLabel::Tracking) diff --git a/src/lib.rs b/src/lib.rs index 2a16709..9151eec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,6 +71,11 @@ pub mod prelude { pub use crate::legacy::prelude::*; } +#[cfg(feature = "iyes_loopless")] +pub use crate::loopless::ProgressSystem; +#[cfg(not(feature = "iyes_loopless"))] +pub use crate::legacy::ProgressSystem; + /// Progress reported by a system /// /// It indicates how much work that system has still left to do. @@ -334,6 +339,31 @@ impl ProgressCounter { } } +/// Trait for all types that can be returned by systems to report progress +pub trait ApplyProgress { + /// Account the value into the total progress for this frame + fn apply_progress(self, total: &ProgressCounter); +} + +impl ApplyProgress for Progress { + fn apply_progress(self, total: &ProgressCounter) { + total.manually_track(self); + } +} + +impl ApplyProgress for HiddenProgress { + fn apply_progress(self, total: &ProgressCounter) { + total.manually_track_hidden(self); + } +} + +impl ApplyProgress for (T, T) { + fn apply_progress(self, total: &ProgressCounter) { + self.0.apply_progress(total); + self.1.apply_progress(total); + } +} + fn loadstate_enter(mut commands: Commands) { commands.insert_resource(ProgressCounter::default()); } diff --git a/src/loopless.rs b/src/loopless.rs index dccd1dc..2efcb65 100644 --- a/src/loopless.rs +++ b/src/loopless.rs @@ -4,10 +4,10 @@ use bevy_ecs::schedule::StateData; use crate::{ProgressPlugin, ProgressSystemLabel}; use crate::ProgressCounter; -use crate::{Progress, HiddenProgress}; +use crate::ApplyProgress; pub mod prelude { - pub use super::{ProgressSystem, HiddenProgressSystem, MixedProgressSystem}; + pub use super::ProgressSystem; } impl Plugin for ProgressPlugin { @@ -70,71 +70,23 @@ impl Plugin for ProgressPlugin { } /// Extension trait for systems with Progress tracking -pub trait ProgressSystem: IntoSystem<(), Progress, Params> { +pub trait ProgressSystem: IntoSystem<(), T, Params> { /// Call this to add your system returning [`Progress`] to your [`App`] /// /// This adds the functionality for tracking the returned Progress. fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor; } -impl ProgressSystem for S +impl ProgressSystem for S where - S: IntoSystem<(), Progress, Params>, + T: ApplyProgress + 'static, + S: IntoSystem<(), T, Params>, { fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor { use iyes_loopless::condition::IntoConditionalSystem; self.chain( - |In(progress): In, counter: Res| { - counter.manually_track(progress); - }, - ) - .into_conditional() - .label(ProgressSystemLabel::Tracking) - } -} - -/// Extension trait for systems with Progress tracking -pub trait HiddenProgressSystem: IntoSystem<(), HiddenProgress, Params> { - /// Call this to add your system returning [`HiddenProgress`] to your [`App`] - /// - /// This adds the functionality for tracking the returned Progress. - fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor; -} - -impl HiddenProgressSystem for S -where - S: IntoSystem<(), HiddenProgress, Params>, -{ - fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor { - use iyes_loopless::condition::IntoConditionalSystem; - self.chain( - |In(progress): In, counter: Res| { - counter.manually_track_hidden(progress); - }, - ) - .into_conditional() - .label(ProgressSystemLabel::Tracking) - } -} - -/// Extension trait for systems with Progress tracking -pub trait MixedProgressSystem: IntoSystem<(), (Progress, HiddenProgress), Params> { - /// Call this to add your system returning both `Progress` and `HiddenProgress` to your [`App`] - /// - /// This adds the functionality for tracking the returned Progress. - fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor; -} - -impl MixedProgressSystem for S -where - S: IntoSystem<(), (Progress, HiddenProgress), Params>, -{ - fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor { - use iyes_loopless::condition::IntoConditionalSystem; - self.chain( - |In((progress, hidden)): In<(Progress, HiddenProgress)>, counter: Res| { - counter.manually_track(progress); - counter.manually_track_hidden(hidden); + |In(progress): In, counter: Res| { + progress.apply_progress(&*counter); }, ) .into_conditional() From 36c910feef75c4ef56c12ed1ac85d71330978878 Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Thu, 18 Aug 2022 18:42:10 +0300 Subject: [PATCH 09/19] add hidden progress to example --- examples/full.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/examples/full.rs b/examples/full.rs index 68eab1d..ffd5592 100644 --- a/examples/full.rs +++ b/examples/full.rs @@ -35,6 +35,7 @@ fn main() { // systems that implement tasks to be tracked for completion: .with_system(net_init_session.track_progress()) .with_system(world_generation.track_progress()) + .with_system(internal_thing.track_progress()) // we can also add regular untracked systems to our loading screen, // like to draw our progress bar: .with_system(ui_progress_bar) @@ -97,6 +98,18 @@ fn world_generation( } } +fn internal_thing( + // ... +) -> HiddenProgress { + // "hidden progress" allows us to report progress + // that is tracked separately, so it is counted for + // the state transition, but not for our user-facing + // progress bar + + // Just wrap the usual `Progress` value in a `HiddenProgress` + HiddenProgress(internal_ready().into()) +} + fn ui_progress_bar( counter: Res, // ... @@ -123,3 +136,7 @@ fn my_session_try_init() { fn gen_chunk(_id: u32) { unimplemented!() } + +fn internal_ready() -> bool { + unimplemented!() +} From 7a19fa211dd74f5bd3f79fdf860257fb509ec5f8 Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Thu, 18 Aug 2022 18:43:46 +0300 Subject: [PATCH 10/19] add dummy systems, they might be useful to someone --- src/lib.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 9151eec..ea9179a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -389,3 +389,31 @@ fn next_frame(world: &mut World) { .total_hidden .store(counter.persisted_hidden.total, MemOrdering::Release); } + +/// Dummy system to count for a number of frames +/// +/// May be useful for testing/debug/workaround purposes. +pub fn dummy_system_wait_frames( + mut count: Local, +) -> HiddenProgress { + if *count <= N { + *count += 1; + } + HiddenProgress(Progress { + done: *count - 1, + total: N, + }) +} + +/// Dummy system to wait for a time duration +/// +/// May be useful for testing/debug/workaround purposes. +pub fn dummy_system_wait_millis( + mut state: Local>, +) -> HiddenProgress { + let end = state.unwrap_or_else( + || std::time::Instant::now() + std::time::Duration::from_millis(MILLIS) + ); + *state = Some(end); + HiddenProgress((std::time::Instant::now() > end).into()) +} From 326d21cbb3c1521a2ef79e7914d62b2eed3d599c Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Thu, 18 Aug 2022 23:18:56 +0300 Subject: [PATCH 11/19] version bump to 0.5.0 --- Cargo.toml | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4c36ebc..cc4c732 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iyes_progress" -version = "0.4.0" +version = "0.5.0" edition = "2021" license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/README.md b/README.md index a8f9a7e..1ab0ddd 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ Bevy Compatibility: |--------------|----------------------| | `main` | `bevy_main` | | `0.8` | `main` | -| `0.8` | `0.4` | -| `0.7` | `0.3`, | +| `0.8` | `0.4`,`0.5` | +| `0.7` | `0.3` | | `0.6` | `bevy_loading = 0.2` | | `0.5` | `bevy_loading = 0.1` | From f621e307af3a767faee107bf1ff5fc463d0dcfbe Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Mon, 24 Oct 2022 16:37:11 +0300 Subject: [PATCH 12/19] update to iyes_loopless 0.8 --- Cargo.toml | 4 ++-- src/loopless.rs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cc4c732..b931390 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ bevy_asset = { version = "0.8", optional = true } bevy_utils = { version = "0.8", optional = true } [dependencies.iyes_loopless] -version = "0.7" +version = "0.8" optional = true default-features = false features = ["states", "app"] @@ -26,7 +26,7 @@ assets = ["bevy_asset", "bevy_utils"] [dev-dependencies] bevy = "0.8" -iyes_loopless = "0.7" +iyes_loopless = "0.8" [[example]] name = "full" diff --git a/src/loopless.rs b/src/loopless.rs index 2efcb65..d33373c 100644 --- a/src/loopless.rs +++ b/src/loopless.rs @@ -12,7 +12,6 @@ pub mod prelude { impl Plugin for ProgressPlugin { fn build(&self, app: &mut App) { - use iyes_loopless::condition::IntoConditionalExclusiveSystem; use iyes_loopless::prelude::*; app.add_enter_system(self.state.clone(), crate::loadstate_enter); @@ -38,6 +37,7 @@ impl Plugin for ProgressPlugin { app.add_system_to_stage( stagelabel, crate::next_frame + .into_conditional_exclusive() .run_in_state(self.state.clone()) .at_start() .label(ProgressSystemLabel::Preparation), @@ -46,6 +46,7 @@ impl Plugin for ProgressPlugin { app.add_system_to_stage( CoreStage::Last, check_progress::(self.next_state.clone()) + .into_conditional_exclusive() .run_in_state(self.state.clone()) .at_end() .label(ProgressSystemLabel::CheckProgress), From 237cebf83d6e3a0d963a12fd0e6e1be2dac45850 Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Tue, 25 Oct 2022 21:18:51 +0300 Subject: [PATCH 13/19] version bump to 0.6.0 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b931390..3147c45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iyes_progress" -version = "0.5.0" +version = "0.6.0" edition = "2021" license = "MIT OR Apache-2.0" readme = "README.md" From 52b187c9c6e31f2774c3b26d8769de2c6fde634e Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Sat, 19 Nov 2022 14:19:16 +0200 Subject: [PATCH 14/19] bevy 0.9 compat --- Cargo.toml | 16 ++++++++-------- README.md | 5 +++-- examples/full.rs | 1 + src/asset.rs | 2 +- src/legacy.rs | 8 +++----- src/lib.rs | 2 +- src/loopless.rs | 4 +--- 7 files changed, 18 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3147c45..448847a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iyes_progress" -version = "0.6.0" +version = "0.7.0" edition = "2021" license = "MIT OR Apache-2.0" readme = "README.md" @@ -10,13 +10,13 @@ categories = ["game-engines"] description = "Bevy plugin to help implement loading states" [dependencies] -bevy_ecs = "0.8" -bevy_app = "0.8" -bevy_asset = { version = "0.8", optional = true } -bevy_utils = { version = "0.8", optional = true } +bevy_ecs = "0.9" +bevy_app = "0.9" +bevy_asset = { version = "0.9", optional = true } +bevy_utils = { version = "0.9", optional = true } [dependencies.iyes_loopless] -version = "0.8" +version = "0.9" optional = true default-features = false features = ["states", "app"] @@ -25,8 +25,8 @@ features = ["states", "app"] assets = ["bevy_asset", "bevy_utils"] [dev-dependencies] -bevy = "0.8" -iyes_loopless = "0.8" +bevy = "0.9" +iyes_loopless = "0.9" [[example]] name = "full" diff --git a/README.md b/README.md index 1ab0ddd..284d9c7 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,9 @@ Bevy Compatibility: | Bevy Version | Plugin Version | |--------------|----------------------| | `main` | `bevy_main` | -| `0.8` | `main` | -| `0.8` | `0.4`,`0.5` | +| `0.9` | `main` | +| `0.9` | `0.7` | +| `0.8` | `0.4`,`0.5`, `0.6` | | `0.7` | `0.3` | | `0.6` | `bevy_loading = 0.2` | | `0.5` | `bevy_loading = 0.1` | diff --git a/examples/full.rs b/examples/full.rs index ffd5592..4b43dda 100644 --- a/examples/full.rs +++ b/examples/full.rs @@ -44,6 +44,7 @@ fn main() { .run(); } +#[derive(Resource)] struct MyUiAssets { ui_font: Handle, btn_img: Handle, diff --git a/src/asset.rs b/src/asset.rs index 896f021..c3d5a76 100644 --- a/src/asset.rs +++ b/src/asset.rs @@ -19,7 +19,7 @@ use crate::Progress; /// It is initialized with the app, so that it is available for you to add /// your asset handles before the load state becomes active. /// On exiting the load state, its value is simply cleared/reset. -#[derive(Default)] +#[derive(Resource, Default)] pub struct AssetsLoading { handles: HashSet, total: u32, diff --git a/src/legacy.rs b/src/legacy.rs index 5bf91c8..9a6e393 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -17,13 +17,11 @@ impl Plugin for ProgressPlugin { SystemSet::on_update(self.state.clone()) .with_system( crate::next_frame - .exclusive_system() .at_start() .label(ProgressSystemLabel::Preparation), ) .with_system( check_progress::(self.next_state.clone()) - .exclusive_system() .at_end() .label(ProgressSystemLabel::CheckProgress), ), @@ -54,7 +52,7 @@ pub trait ProgressSystem: IntoSystem<(), T, Params> { /// Call this to add your system returning [`Progress`] to your [`App`] /// /// This adds the functionality for tracking the returned Progress. - fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor; + fn track_progress(self) -> bevy_ecs::schedule::SystemDescriptor; } impl ProgressSystem for S @@ -62,8 +60,8 @@ where T: ApplyProgress + 'static, S: IntoSystem<(), T, Params>, { - fn track_progress(self) -> bevy_ecs::schedule::ParallelSystemDescriptor { - self.chain( + fn track_progress(self) -> bevy_ecs::schedule::SystemDescriptor { + self.pipe( |In(progress): In, counter: Res| { progress.apply_progress(&*counter); }, diff --git a/src/lib.rs b/src/lib.rs index ea9179a..44d8d4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -244,7 +244,7 @@ pub enum ProgressSystemLabel { /// /// This resource is automatically created when entering a state that was /// configured using [`ProgressPlugin`], and removed when exiting it. -#[derive(Default)] +#[derive(Resource, Default)] pub struct ProgressCounter { // use atomics to track overall progress, // so that we can avoid mut access in tracked systems, diff --git a/src/loopless.rs b/src/loopless.rs index d33373c..6f72e64 100644 --- a/src/loopless.rs +++ b/src/loopless.rs @@ -37,7 +37,6 @@ impl Plugin for ProgressPlugin { app.add_system_to_stage( stagelabel, crate::next_frame - .into_conditional_exclusive() .run_in_state(self.state.clone()) .at_start() .label(ProgressSystemLabel::Preparation), @@ -46,7 +45,6 @@ impl Plugin for ProgressPlugin { app.add_system_to_stage( CoreStage::Last, check_progress::(self.next_state.clone()) - .into_conditional_exclusive() .run_in_state(self.state.clone()) .at_end() .label(ProgressSystemLabel::CheckProgress), @@ -85,7 +83,7 @@ where { fn track_progress(self) -> iyes_loopless::condition::ConditionalSystemDescriptor { use iyes_loopless::condition::IntoConditionalSystem; - self.chain( + self.pipe( |In(progress): In, counter: Res| { progress.apply_progress(&*counter); }, From 325ef88e61145e4e8b7209dbc140370aaca8cdc3 Mon Sep 17 00:00:00 2001 From: Niklas Eicker Date: Sat, 19 Nov 2022 21:31:33 +0100 Subject: [PATCH 15/19] Mark progress plugin as not unique (#18) --- src/legacy.rs | 4 ++++ src/loopless.rs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/legacy.rs b/src/legacy.rs index 9a6e393..fd3b7e6 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -45,6 +45,10 @@ impl Plugin for ProgressPlugin { panic!("Enable the \"assets\" cargo feature to use assets tracking!"); } } + + fn is_unique(&self) -> bool { + false + } } /// Extension trait for systems with progress tracking diff --git a/src/loopless.rs b/src/loopless.rs index 6f72e64..80f84f6 100644 --- a/src/loopless.rs +++ b/src/loopless.rs @@ -66,6 +66,10 @@ impl Plugin for ProgressPlugin { panic!("Enable the \"assets\" cargo feature to use assets tracking!"); } } + + fn is_unique(&self) -> bool { + false + } } /// Extension trait for systems with Progress tracking From eadc979907a49b73c5e4773cbf6744a90ae05d7c Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Sun, 20 Nov 2022 11:28:34 +0200 Subject: [PATCH 16/19] Version bump to 0.7.1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 448847a..b1923c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iyes_progress" -version = "0.7.0" +version = "0.7.1" edition = "2021" license = "MIT OR Apache-2.0" readme = "README.md" From ef54a863345322cf4620e93496be893506964ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 22 Nov 2022 13:47:53 +0100 Subject: [PATCH 17/19] unique name for each plugin instance (#19) --- src/legacy.rs | 4 ++-- src/lib.rs | 3 +++ src/loopless.rs | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/legacy.rs b/src/legacy.rs index fd3b7e6..41fe851 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -46,8 +46,8 @@ impl Plugin for ProgressPlugin { } } - fn is_unique(&self) -> bool { - false + fn name(&self) -> &str { + &self.plugin_name } } diff --git a/src/lib.rs b/src/lib.rs index 44d8d4d..e96b2ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -193,12 +193,15 @@ pub struct ProgressPlugin { pub next_state: Option, /// Whether to enable the optional assets tracking feature pub track_assets: bool, + // Unique name, made using the loading state + pub(crate) plugin_name: String, } impl ProgressPlugin { /// Create a [`ProgressPlugin`] running during the given State pub fn new(state: S) -> Self { ProgressPlugin { + plugin_name: format!("{}({:?})", std::any::type_name::(), state), state, next_state: None, track_assets: false, diff --git a/src/loopless.rs b/src/loopless.rs index 80f84f6..55a1f73 100644 --- a/src/loopless.rs +++ b/src/loopless.rs @@ -67,8 +67,8 @@ impl Plugin for ProgressPlugin { } } - fn is_unique(&self) -> bool { - false + fn name(&self) -> &str { + &self.plugin_name } } From 12e7058374657fbda6b51fb9e75cf26406dd6c30 Mon Sep 17 00:00:00 2001 From: Ida Iyes Date: Thu, 9 Mar 2023 23:38:39 +0200 Subject: [PATCH 18/19] add note about issue #20 --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index d4172c8..46e6227 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -141,7 +141,8 @@ pub struct HiddenProgress(pub Progress); /// Add this plugin to your app, to use this crate for the specified state. /// /// If you have multiple different states that need progress tracking, -/// you can add the plugin for each one. +/// you can add the plugin for each one. Tracking multiple state types +/// simultaneously is *not* currently supported (see issue #20). /// /// If you want the optional assets tracking ("assets" cargo feature), enable /// it with `.track_assets()`. From e4f58c03e16bdd47cf346fe7c11ecd677523648f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pazos=20P=C3=A9rez?= Date: Fri, 14 Apr 2023 01:37:31 +0200 Subject: [PATCH 19/19] Bump Bevy to main 0.11-dev --- Cargo.toml | 10 +++++----- examples/full.rs | 12 ++++-------- src/lib.rs | 51 ++++++++++++++++++++++-------------------------- 3 files changed, 32 insertions(+), 41 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cad9782..62b79ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,16 +10,16 @@ categories = ["game-engines"] description = "Bevy plugin to help implement loading states" [dependencies] -bevy_ecs = { version = "0.10" } -bevy_app = { version = "0.10" } -bevy_asset = { version = "0.10", optional = true } -bevy_utils = { version = "0.10", optional = true } +bevy_ecs = { git = "https://github.com/bevyengine/bevy" } +bevy_app = { git = "https://github.com/bevyengine/bevy" } +bevy_asset = { git = "https://github.com/bevyengine/bevy", optional = true } +bevy_utils = { git = "https://github.com/bevyengine/bevy", optional = true } [features] assets = ["bevy_asset", "bevy_utils"] [dev-dependencies] -bevy = { version = "0.10" } +bevy = { git = "https://github.com/bevyengine/bevy" } [[example]] name = "full" diff --git a/examples/full.rs b/examples/full.rs index d843a5f..a480e9f 100644 --- a/examples/full.rs +++ b/examples/full.rs @@ -27,28 +27,24 @@ fn main() { // Add plugin for our game loading screen .add_plugin(ProgressPlugin::new(AppState::GameLoading).continue_to(AppState::InGame)) // Load our UI assets during our splash screen - .add_system(load_ui_assets.in_schedule(OnEnter(AppState::Splash))) + .add_systems(OnEnter(AppState::Splash), load_ui_assets) // Our game loading screen // systems that implement tasks to be tracked for completion: .add_systems( + Update, ( net_init_session.track_progress(), world_generation.track_progress(), internal_thing.track_progress(), // we can also add regular untracked systems to our loading screen, // like to draw our progress bar: - ui_progress_bar, + ui_progress_bar.after(ProgressSystemSet::CheckProgress), ) - .in_set(LoadingSystems), + .run_if(in_state(AppState::GameLoading)), ) - .configure_set(LoadingSystems.run_if(in_state(AppState::GameLoading))) .run(); } -// Todo: remove after https://github.com/bevyengine/bevy/pull/7676 -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, SystemSet)] -struct LoadingSystems; - #[derive(Resource)] struct MyUiAssets { ui_font: Handle, diff --git a/src/lib.rs b/src/lib.rs index 46e6227..48adca2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,7 +37,6 @@ #![forbid(unsafe_code)] #![warn(missing_docs)] -use bevy_ecs::schedule::SystemConfig; use std::fmt::Debug; use std::hash::Hash; use std::ops::{Add, AddAssign}; @@ -45,7 +44,7 @@ use std::sync::atomic::AtomicU32; use std::sync::atomic::Ordering as MemOrdering; use bevy_app::prelude::*; -use bevy_ecs::prelude::*; +use bevy_ecs::{prelude::*, schedule::SystemConfigs}; #[cfg(feature = "assets")] mod asset; @@ -58,6 +57,7 @@ pub mod prelude { pub use crate::ProgressCounter; pub use crate::ProgressPlugin; pub use crate::ProgressSystem; + pub use crate::ProgressSystemSet; } /// Progress reported by a system @@ -208,34 +208,31 @@ impl ProgressPlugin { impl Plugin for ProgressPlugin { fn build(&self, app: &mut App) { - app.add_system(loadstate_enter.in_schedule(OnEnter(self.state.clone()))) - .add_system( - next_frame - .in_base_set(ProgressSystemSet::Preparation) + app.add_systems(OnEnter(self.state.clone()), loadstate_enter) + .add_systems( + Update, + ( + next_frame + .before(TrackedProgressSet) + .in_set(ProgressSystemSet::Preparation), + check_progress::(self.next_state.clone()) + .after(TrackedProgressSet) + .in_set(ProgressSystemSet::CheckProgress), + ) .run_if(in_state(self.state.clone())), ) - .configure_set( - ProgressSystemSet::Preparation - .after(CoreSet::StateTransitions) - .before(TrackedProgressSet), - ) - .add_system( - check_progress::(self.next_state.clone()) - .in_base_set(ProgressSystemSet::CheckProgress) - .run_if(in_state(self.state.clone())), - ) - .configure_set(ProgressSystemSet::CheckProgress.after(TrackedProgressSet)) - .add_system(loadstate_exit.in_schedule(OnExit(self.state.clone()))); + .add_systems(OnExit(self.state.clone()), loadstate_exit); #[cfg(feature = "assets")] if self.track_assets { app.init_resource::(); - app.add_system( + app.add_systems( + Update, asset::assets_progress .track_progress() .run_if(in_state(self.state.clone())), ); - app.add_system(asset::assets_loading_reset.in_schedule(OnExit(self.state.clone()))); + app.add_systems(OnExit(self.state.clone()), asset::assets_loading_reset); } #[cfg(not(feature = "assets"))] @@ -254,7 +251,7 @@ pub trait ProgressSystem: IntoSystem<(), T, Params> { /// Call this to add your system returning [`Progress`] to your [`App`] /// /// This adds the functionality for tracking the returned Progress. - fn track_progress(self) -> SystemConfig; + fn track_progress(self) -> SystemConfigs; } impl ProgressSystem for S @@ -262,9 +259,9 @@ where T: ApplyProgress + 'static, S: IntoSystem<(), T, Params>, { - fn track_progress(self) -> SystemConfig { + fn track_progress(self) -> SystemConfigs { self.pipe(|In(progress): In, counter: Res| { - progress.apply_progress(&*counter); + progress.apply_progress(&counter); }) .in_set(TrackedProgressSet) } @@ -280,14 +277,12 @@ fn check_progress(next_state: Option) -> impl FnMut(Res