206 lines
6.7 KiB
Rust
206 lines
6.7 KiB
Rust
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 {
|
|
// 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,
|
|
});
|
|
}
|