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<Image>,
#[asset(path = "plane_map.ktx2")]
pub plane_lightmap: Handle<Image>,
#[asset(path = "scene.glb#Scene0")]
pub scene: Handle<Scene>,
}
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<MenuData>) {
commands.entity(menu_data.button_entity).despawn_recursive();
}
fn menu(
mut next_state: ResMut<NextState<AppState>>,
mut interaction_query: Query<(&Interaction, &MenuButton), Changed<Interaction>>,
mut app_exit_events: EventWriter<AppExit>,
) {
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<MenuAssets>,
mut clear_color: ResMut<ClearColor>,
mut materials: ResMut<Assets<StandardMaterial>>,
meshes: Query<
(Entity, &Name, &Handle<StandardMaterial>),
(With<Handle<Mesh>>, Without<Lightmap>),
>,
) {
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 {
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 {
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.),
justify_content: JustifyContent::Center,
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.),
justify_content: JustifyContent::Center,
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),
..Default::default()
});
commands.insert_resource(AmbientLight::NONE);
commands.insert_resource(MenuData {
button_entity,
logo_bw_entity,
});
}