diff --git a/assets/martian.tweak.toml b/assets/martian.tweak.toml index 438b662..4ce03c8 100644 --- a/assets/martian.tweak.toml +++ b/assets/martian.tweak.toml @@ -229,6 +229,7 @@ title = "Title" [title] image = "images/title.png" +fade_in_seconds = 6.0 width_px = 400.0 [display3d.models.animations] diff --git a/src/display3d.rs b/src/display3d.rs index a26942b..efb5188 100644 --- a/src/display3d.rs +++ b/src/display3d.rs @@ -99,7 +99,6 @@ impl Plugin for Display3dPlugin { .or_else(any_component_removed::()), ), set_board_model.run_if(any_component_added::()), - set_title_model.run_if(any_component_added::()), set_valid_move_model.run_if(any_component_added::()), set_tile_hitbox.run_if(any_component_added::()), dissolve_animation.run_if(any_with_component::), @@ -164,17 +163,21 @@ impl Plugin for Display3dPlugin { .add_systems( OnEnter(GameState::Title), ( - intro_title_dissolve, + fade_title_in, fixup_shadows ) ) - .add_systems(OnExit(GameState::Title), outro_title_dissolve) + .add_systems(OnExit(GameState::Title), fade_title_out) .add_systems( Update, - continue_title - .run_if(in_state(GameState::Title)) - .run_if(not(any_with_component::)) - .run_if(just_pressed(KeyCode::Enter).or_else(just_pressed(MouseButton::Left))), + ( + fade_title + .run_if(any_with_component::), + continue_title + .run_if(in_state(GameState::Title)) + .run_if(not(any_with_component::)) + .run_if(just_pressed(KeyCode::Enter).or_else(just_pressed(MouseButton::Left))), + ) ); } } @@ -197,6 +200,12 @@ pub(crate) enum Dissolving { Out(f32), } +#[derive(Debug, Component)] +pub(crate) enum Fading { + In(f32), + Out(f32), +} + #[derive(Debug, Resource)] pub(crate) struct AnimationSpeed { pub movement: f32, @@ -216,6 +225,7 @@ impl Default for AnimationSpeed { struct AssetsMap { hitbox_shape: Handle, hitbox_material: Handle, + title_image: Handle, } /// Load 3d models @@ -225,6 +235,8 @@ fn load_assets( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, + tweaks_file: Res, + tweaks: Res>, ) { let hitbox_shape = meshes.add(Cuboid::new(1.0, 0.1, 1.0)); let hitbox_material = materials.add(StandardMaterial { @@ -234,15 +246,46 @@ fn load_assets( alpha_mode: AlphaMode::Blend, ..default() }); + + let tweak = tweaks + .get(tweaks_file.handle.clone()) + .expect("Load tweakfile"); + let title_image = tweak.get_handle::("title_image").unwrap(); + commands.insert_resource(AssetsMap { hitbox_shape, hitbox_material, + title_image, }); } /// Initialize the board and pieces fn initialize(mut commands: Commands, board: Res, assets: Res) { debug!("Initializing root"); + // Title + commands.spawn(( + DisplayState::Display3d, + Display3d, + ImageBundle { + style: Style { + width: Val::Percent(75.0), + height: Val::Percent(75.0), + align_self: AlignSelf::Center, + justify_self: JustifySelf::Center, + ..default() + }, + background_color: Color::WHITE.with_a(0.0).into(), + image: UiImage { + texture: assets.title_image.clone(), + ..default() + }, + visibility: Visibility::Hidden, + ..default() + }, + TitleText, + )); + + // 3D objects root commands .spawn(( SpatialBundle { @@ -254,22 +297,6 @@ fn initialize(mut commands: Commands, board: Res, assets: Res, &mut Transform, &mut Visibility), - (Added, With), - >, - gltfs: Res>, - tweaks: Res>, - tweaks_file: Res, -) { - let tweak = tweaks - .get(tweaks_file.handle.clone()) - .expect("Load tweakfile"); - titles - .iter_mut() - .for_each(|(mut handle, mut transform, mut visibility)| { - debug!("Setting title model"); - let assets_handle = tweak - .get_handle::("display3d_models_assets_file") - .unwrap(); - let gltf = gltfs.get(assets_handle).expect("Load GLTF content"); - *handle = gltf - .named_scenes - .get( - tweak - .get::("display3d_models_scenes_title") - .unwrap() - .as_str(), - ) - .expect("Game title model") - .clone(); - - transform.translation -= Vec3::Y * 0.5; - transform.rotate_local_z(std::f32::consts::PI); - transform.rotate_local_y(std::f32::consts::PI / 2.0); - - *visibility = Visibility::Hidden; - }); -} - /// Given a board index returns the Vec3 location in space fn board_translation(&BoardIndex { x, y }: &BoardIndex) -> Vec3 { // Scale x down by 4 to account for -4..4 scaling @@ -1269,28 +1257,6 @@ fn monitor_animations( }); } -fn intro_title_dissolve( - mut query: Query<(Entity, &Dissolvable), With>, - mut commands: Commands, -) { - query.iter_mut().for_each(|(entity, dissolving)| { - commands - .entity(entity) - .insert(Dissolving::In(dissolving.duration)); - }); -} - -fn outro_title_dissolve( - mut query: Query<(Entity, &Dissolvable), With>, - mut commands: Commands, -) { - query.iter_mut().for_each(|(entity, dissolving)| { - commands - .entity(entity) - .insert(Dissolving::Out(dissolving.duration)); - }); -} - fn continue_title(mut next_state: ResMut>) { next_state.set(GameState::Play) } @@ -1438,3 +1404,71 @@ fn bloom_tweak( bloom.intensity = tweak.get::("color_bloom_intensity").unwrap(); }) } + +fn fade_title_in( + query: Query>, + tweaks: Res>, + tweaks_file: Res, + mut commands: Commands, +) { + let tweak = tweaks + .get(tweaks_file.handle.clone()) + .expect("Load tweakfile"); + let seconds = tweak.get::("title_fade_in_seconds").unwrap(); + + query.iter().for_each(|e| { + commands.entity(e).insert(Fading::In(seconds)); + }) +} + +fn fade_title_out( + query: Query>, + tweaks: Res>, + tweaks_file: Res, + mut commands: Commands, +) { + let tweak = tweaks + .get(tweaks_file.handle.clone()) + .expect("Load tweakfile"); + let seconds = tweak.get::("title_fade_in_seconds").unwrap(); + + query.iter().for_each(|e| { + commands.entity(e).insert(Fading::Out(seconds)); + }) +} + +fn fade_title( + mut query: Query<(Entity, &mut BackgroundColor, &mut Visibility, &Fading), With>, + time: Res