use bevy::app::Plugin; use bevy::asset::{Handle, LoadState}; use bevy::ecs::schedule::ShouldRun; use bevy::prelude::*; use bevy_kira_audio::AudioSource; /// We store our asset handles in this to avoid Bevy from dropping the assets and reloading /// when we switch tracks pub struct AudioResources { pub white_kitty: Handle<AudioSource>, pub great_madeja: Handle<AudioSource>, } #[derive(Default, Eq, PartialEq, Debug, Clone, Hash)] pub enum AppState { #[default] Loading, Running, } pub fn load_resources(mut commands: Commands, assets: Res<AssetServer>) { let white_kitty = assets.load("The-White-Kitty.mp3"); let great_madeja = assets.load("The-Great-Madeja.mp3"); commands.insert_resource(AudioResources { white_kitty, great_madeja, }) } pub fn check_load_state( assets: Res<AssetServer>, resources: Res<AudioResources>, mut appstate: ResMut<State<AppState>>, ) { let load_state = assets.get_group_load_state(vec![resources.white_kitty.id, resources.great_madeja.id]); match load_state { LoadState::Loaded => { appstate.set(AppState::Running); } LoadState::Loading => {} _ => { log::error!("The resources are in a bad state! This is a problem"); } } } pub fn has_audio_resources(res: Option<Res<AudioResources>>) -> ShouldRun { res.is_some().into() } pub fn is_state_loading(state: Res<AppState>) -> ShouldRun { (*state == AppState::Loading).into() } pub fn is_state_running(state: Res<AppState>) -> ShouldRun { (*state == AppState::Running).into() } /// This component allows us to easily grab the on screen text #[derive(Component)] pub struct TextMarker; /// This component allows us to easily grab the blank details text area #[derive(Component)] pub struct DetailsMarker; pub fn create_ui(mut commands: Commands, assets: Res<AssetServer>) { commands.spawn_bundle(Camera2dBundle::default()); commands .spawn_bundle(NodeBundle { style: Style { size: Size::new(Val::Percent(100.0), Val::Percent(100.0)), justify_content: JustifyContent::Center, align_items: AlignItems::Center, flex_direction: FlexDirection::Column, ..Default::default() }, ..Default::default() }) .with_children(|children| { children .spawn_bundle(TextBundle { text: Text::from_section( "Loading Audio Tracks", TextStyle { color: Color::BLACK, font_size: 48.0, font: assets.load("KenneyBlocks.ttf"), }, ), ..Default::default() }) .insert(TextMarker); children .spawn_bundle(TextBundle { text: Text::from_section( "...", TextStyle { color: Color::BLACK, font_size: 32.0, font: assets.load("KenneyBlocks.ttf"), }, ), ..Default::default() }) .insert(DetailsMarker); }); } pub struct SetupPlugin; impl Plugin for SetupPlugin { fn build(&self, app: &mut App) { app.add_state(AppState::Loading) .insert_resource(WindowDescriptor { width: 800.0, height: 600.0, title: String::from("Kitchen Sink Example"), ..Default::default() }) .add_startup_system(load_resources) .add_startup_system(create_ui) .add_system_set( SystemSet::on_update(AppState::Loading) .with_run_criteria(has_audio_resources) .with_system(check_load_state), ); } }