diff --git a/src/screens/splash.rs b/src/screens/splash.rs index 5bd7b06..8a6da3c 100644 --- a/src/screens/splash.rs +++ b/src/screens/splash.rs @@ -1,5 +1,7 @@ //! A splash screen that plays briefly at startup. +use std::collections::VecDeque; + use bevy::{ input::common_conditions::input_just_pressed, prelude::*, @@ -12,6 +14,8 @@ use crate::{theme::prelude::*, AppSet}; pub(super) fn plugin(app: &mut App) { // Spawn splash screen. app.insert_resource(ClearColor(SPLASH_BACKGROUND_COLOR)); + app.init_resource::(); + app.add_systems(OnEnter(Screen::Splash), spawn_splash); // Animate splash screen. @@ -49,11 +53,71 @@ const SPLASH_BACKGROUND_COLOR: Color = Color::srgb(0.157, 0.157, 0.157); const SPLASH_DURATION_SECS: f32 = 1.8; const SPLASH_FADE_DURATION_SECS: f32 = 0.6; +#[derive(Component)] +struct SplashScreenContainer; + +#[derive(Resource)] +struct SplashScreenImageList(VecDeque<&'static str>); + +impl Default for SplashScreenImageList { + fn default() -> Self { + // Use paths here rather than an ImageHandle as the loading screen hasn't + // run yet. To show your own splash images, replace or add here + Self(VecDeque::from_iter(["images/splash.png"].into_iter())) + } +} fn exit_splash_screen(mut next_screen: ResMut>) { next_screen.set(Screen::Loading); } +fn splash_image_bundle(asset_server: &AssetServer, path: &'static str) -> impl Bundle { + ( + Name::new("Splash image"), + ImageBundle { + style: Style { + margin: UiRect::all(Val::Auto), + width: Val::Percent(70.0), + ..default() + }, + image: UiImage::new(asset_server.load_with_settings( + // This should be an embedded asset for instant loading, but that is + // currently [broken on Windows Wasm builds](https://github.com/bevyengine/bevy/issues/14246). + path, + |settings: &mut ImageLoaderSettings| { + // Make an exception for the splash image in case + // `ImagePlugin::default_nearest()` is used for pixel art. + settings.sampler = ImageSampler::linear(); + }, + )), + background_color: BackgroundColor(Color::srgba(0., 0., 0., 0.)), + ..default() + }, + UiImageFadeInOut { + total_duration: SPLASH_DURATION_SECS, + fade_duration: SPLASH_FADE_DURATION_SECS, + t: 0.0, + }, + ) +} + +fn spawn_splash( + mut commands: Commands, + splash_images: Res, + mut next_screen: ResMut>, +) { + if splash_images.0.is_empty() { + // if there are no splash images, go directly to the loading screen + next_screen.set(Screen::Loading); + } else { + // spawn the UI root but wait for the first timer tick to show an image + commands.ui_root().insert(( + Name::new("Splash screen container"), + BackgroundColor(SPLASH_BACKGROUND_COLOR), + StateScoped(Screen::Splash), + SplashScreenContainer, + )); + } } #[derive(Component, Reflect)] @@ -112,8 +176,35 @@ fn tick_splash_timer(time: Res