use bevy::{app::AppExit, pbr::Lightmap, prelude::*}; use bevy_asset_loader::asset_collection::AssetCollection; use crate::AppState; pub struct MenuPlugin; #[derive(Resource, AssetCollection)] pub struct MenuAssets { #[asset(path = "logo_bw.ktx2")] pub logo: Handle, #[asset(path = "plane_map.ktx2")] pub plane_lightmap: Handle, #[asset(path = "scene.glb#Scene0")] pub scene: Handle, } const NORMAL_BUTTON: Color = Color::BLACK; impl Plugin for MenuPlugin { fn build(&self, app: &mut App) { app.add_systems(OnEnter(AppState::Menu), setup_menu) .add_systems(Update, menu.run_if(in_state(AppState::Menu))) .add_systems(OnExit(AppState::Menu), cleanup_menu); } } #[derive(Component)] enum MenuButton { Play, Quit, } #[derive(Resource, Clone, Copy)] pub struct MenuData { pub button_entity: Entity, pub logo_bw_entity: Entity, } fn cleanup_menu(mut commands: Commands, menu_data: Res) { commands.entity(menu_data.button_entity).despawn_recursive(); } fn menu( mut next_state: ResMut>, mut interaction_query: Query<(&Interaction, &MenuButton), Changed>, mut app_exit_events: EventWriter, ) { for (interaction, button_type) in &mut interaction_query { match *interaction { Interaction::Pressed => match *button_type { MenuButton::Play => next_state.set(AppState::Rooms), MenuButton::Quit => { app_exit_events.send(AppExit); } }, _ => {} } } } fn setup_menu( mut commands: Commands, assets: Res, mut clear_color: ResMut, mut materials: ResMut>, meshes: Query< (Entity, &Name, &Handle), (With>, Without), >, ) { let exposure = 250.0; clear_color.0 = Color::BLACK; for (entity, name, material) in meshes.iter() { if &**name == "Light" { materials.get_mut(material).unwrap().emissive = Color::WHITE * exposure; continue; } if &**name == "Plane" { materials.get_mut(material).unwrap().lightmap_exposure = exposure; commands.entity(entity).insert(Lightmap { image: assets.plane_lightmap.clone(), ..default() }); continue; } } let logo_bw_entity = commands .spawn(NodeBundle { style: Style { // center button width: Val::Percent(100.), height: Val::Percent(100.), justify_content: JustifyContent::FlexStart, align_items: AlignItems::End, ..default() }, ..Default::default() }) .with_children(|parent| { parent.spawn(ImageBundle { style: Style { width: Val::Auto, height: Val::Auto, justify_content: JustifyContent::FlexStart, align_items: AlignItems::Start, ..Default::default() }, image: UiImage { texture: assets.logo.clone(), ..Default::default() }, ..Default::default() }); }) .id(); let button_entity = commands .spawn(NodeBundle { style: Style { // center button width: Val::Percent(100.), height: Val::Percent(100.), justify_content: JustifyContent::Center, align_items: AlignItems::Center, flex_direction: FlexDirection::Column, ..default() }, ..default() }) .with_children(|parent| { parent .spawn(( ButtonBundle { style: Style { width: Val::Px(150.), height: Val::Px(65.), // horizontally center child text justify_content: JustifyContent::Center, // vertically center child text align_items: AlignItems::Center, margin: UiRect { bottom: Val::Px(16.0), ..Default::default() }, ..default() }, background_color: NORMAL_BUTTON.into(), ..default() }, MenuButton::Play, )) .with_children(|parent| { parent.spawn(TextBundle::from_section( "Play", TextStyle { font_size: 40.0, color: Color::rgb(0.9, 0.9, 0.9), ..default() }, )); }); parent .spawn(( ButtonBundle { style: Style { width: Val::Px(150.), height: Val::Px(65.), // horizontally center child text justify_content: JustifyContent::Center, // vertically center child text align_items: AlignItems::Center, margin: UiRect { bottom: Val::Px(16.0), ..Default::default() }, ..default() }, background_color: NORMAL_BUTTON.into(), ..default() }, MenuButton::Quit, )) .with_children(|parent| { parent.spawn(TextBundle::from_section( "Quit", TextStyle { font_size: 40.0, color: Color::rgb(0.9, 0.9, 0.9), ..default() }, )); }); }) .id(); commands.spawn(Camera3dBundle { transform: Transform::from_xyz(0.0, -585.9, 193.0), // .with_rotation(Quat::from_rotation_x(71.0)), ..Default::default() }); commands.insert_resource(AmbientLight::NONE); commands.insert_resource(MenuData { button_entity, logo_bw_entity, }); }