use super::*; /// Systems run during loading state pub struct LoadingPlugin; impl Plugin for LoadingPlugin { fn build(&self, app: &mut App) { // PERF: We check all asset classes every frame, should be event based app.init_resource::() .init_state::() .add_systems(PreUpdate, reset_progress) .add_systems(Startup, spawn_loading_screen) .add_systems( Update, ( ( track_loading::, track_loading::, track_loading::, track_loading::, track_loading::, track_loading::, ) .run_if(in_state(LoadingState::Active)), toggle_state_visibility::.run_if(state_changed::), ), ) .add_systems(PostUpdate, check_progress); } } #[derive(States, Clone, PartialEq, Eq, Hash, Debug, Default, Component)] pub enum LoadingState { #[default] Active, Idle, } /// Resource for tracking asset loading progress #[derive(Resource, Default)] struct TrackLoadingProgress(Vec); fn spawn_loading_screen(mut commands: Commands) { commands.spawn(( Node { align_self: AlignSelf::Center, justify_self: JustifySelf::Center, ..default() }, LoadingState::Active, children![( TextColor(WHITE.into()), Text::new("Credits"), BackgroundColor(BLACK.into()) )], )); } /// At the start of the update clear progress fn reset_progress(mut progress: ResMut) { progress.0.clear() } /// Track the progress of all assets in this asset class fn track_loading( assets: Res>, server: Res, mut progress: ResMut, ) { let all_loaded = assets .ids() .map(|id| server.load_state(id)) .all(|load_state| !load_state.is_loading() && !load_state.is_failed()); progress.0.push(all_loaded); } /// At the end of the frame check if all asset classes are loaded fn check_progress( progress: Res, mut next_state: ResMut>, ) { if progress.0.iter().all(|x| *x) { next_state.set(LoadingState::Idle); } }