diff --git a/crates/border-wars/assets/menu/airplane.png b/crates/border-wars/assets/menu/airplane.png new file mode 100644 index 0000000..382d37d Binary files /dev/null and b/crates/border-wars/assets/menu/airplane.png differ diff --git a/crates/border-wars/assets/menu/border_wars.png b/crates/border-wars/assets/menu/border_wars.png new file mode 100644 index 0000000..9825c7c Binary files /dev/null and b/crates/border-wars/assets/menu/border_wars.png differ diff --git a/crates/border-wars/assets/menu/button.png b/crates/border-wars/assets/menu/button.png new file mode 100644 index 0000000..c31c44b Binary files /dev/null and b/crates/border-wars/assets/menu/button.png differ diff --git a/crates/border-wars/assets/menu/bw_menu_bg.png b/crates/border-wars/assets/menu/bw_menu_bg.png new file mode 100644 index 0000000..daaab8b Binary files /dev/null and b/crates/border-wars/assets/menu/bw_menu_bg.png differ diff --git a/crates/border-wars/assets/menu/host.png b/crates/border-wars/assets/menu/host.png new file mode 100644 index 0000000..bd19fe5 Binary files /dev/null and b/crates/border-wars/assets/menu/host.png differ diff --git a/crates/border-wars/assets/menu/host_icon.png b/crates/border-wars/assets/menu/host_icon.png new file mode 100644 index 0000000..881c7bb Binary files /dev/null and b/crates/border-wars/assets/menu/host_icon.png differ diff --git a/crates/border-wars/assets/menu/info.png b/crates/border-wars/assets/menu/info.png new file mode 100644 index 0000000..7ce0889 Binary files /dev/null and b/crates/border-wars/assets/menu/info.png differ diff --git a/crates/border-wars/assets/menu/info_hover.png b/crates/border-wars/assets/menu/info_hover.png new file mode 100644 index 0000000..1590bcb Binary files /dev/null and b/crates/border-wars/assets/menu/info_hover.png differ diff --git a/crates/border-wars/assets/menu/join.png b/crates/border-wars/assets/menu/join.png new file mode 100644 index 0000000..fbeb77e Binary files /dev/null and b/crates/border-wars/assets/menu/join.png differ diff --git a/crates/border-wars/assets/menu/join_icon.png b/crates/border-wars/assets/menu/join_icon.png new file mode 100644 index 0000000..c43c26c Binary files /dev/null and b/crates/border-wars/assets/menu/join_icon.png differ diff --git a/crates/border-wars/assets/menu/setting.png b/crates/border-wars/assets/menu/setting.png new file mode 100644 index 0000000..50895d0 Binary files /dev/null and b/crates/border-wars/assets/menu/setting.png differ diff --git a/crates/border-wars/assets/menu/setting_hover.png b/crates/border-wars/assets/menu/setting_hover.png new file mode 100644 index 0000000..c8ae15e Binary files /dev/null and b/crates/border-wars/assets/menu/setting_hover.png differ diff --git a/crates/border-wars/assets/menu/trait.png b/crates/border-wars/assets/menu/trait.png new file mode 100644 index 0000000..b029907 Binary files /dev/null and b/crates/border-wars/assets/menu/trait.png differ diff --git a/crates/border-wars/src/lib.rs b/crates/border-wars/src/lib.rs index 366b111..54d0eca 100644 --- a/crates/border-wars/src/lib.rs +++ b/crates/border-wars/src/lib.rs @@ -12,7 +12,7 @@ pub mod scenes; pub mod ui; /// A scene of the game. -#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)] +#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States, Component)] pub enum Scene { /// When we are in the main menu. #[default] diff --git a/crates/border-wars/src/scenes/menu.rs b/crates/border-wars/src/scenes/menu.rs index a13de1a..ebb135a 100644 --- a/crates/border-wars/src/scenes/menu.rs +++ b/crates/border-wars/src/scenes/menu.rs @@ -1,79 +1,320 @@ //! The main menu of the game. -use bevnet::{Connection, SendTo, Uuid}; +// use bevnet::{Connection, SendTo, Uuid}; use bevy::prelude::*; -use bevy_egui::{egui, EguiContexts}; +// use bevy_egui::{egui, EguiContexts}; -use crate::networking::connection::RequestJoin; -use crate::networking::PlayerRank; -use crate::{CurrentScene, Player}; +// use crate::networking::connection::RequestJoin; +// use crate::networking::PlayerRank; +use crate::ui::hover::HoveredTexture; +use crate::CurrentScene; +// use crate::Player; /// The plugin for the menu. pub struct MenuPlugin; impl Plugin for MenuPlugin { fn build(&self, app: &mut App) { - app.add_systems(Update, menu_ui.run_if(in_state(CurrentScene::Menu))); + // app.add_systems(Update, menu_ui.run_if(in_state(CurrentScene::Menu))); + app.add_systems(OnEnter(CurrentScene::Menu), menu_ui); } } -/// Display the UI of the menu to host a game or join one. -fn menu_ui( - mut ctx: EguiContexts, - mut connection_string: Local, - mut next_scene: ResMut>, - mut request_join: EventWriter>, - mut name: Local, - connection: Res, - mut commands: Commands, -) { - let Some(uuid) = connection.identifier() else { - return; - }; +#[derive(Component)] +struct Host; - egui::CentralPanel::default().show(ctx.ctx_mut(), |ui| { - ui.heading("Border Wars"); +#[derive(Component)] +struct Join; - ui.separator(); +// Display the UI of the menu to host a game or join one. +// fn old_menu( +// mut ctx: EguiContexts, +// mut connection_string: Local, +// mut next_scene: ResMut>, +// mut request_join: EventWriter>, +// mut name: Local, +// connection: Res, +// mut commands: Commands, +// ) { +// let Some(uuid) = connection.identifier() else { +// return; +// }; - ui.label("Name"); - ui.text_edit_singleline(&mut *name); +// egui::CentralPanel::default().show(ctx.ctx_mut(), |ui| { +// ui.heading("Border Wars"); - ui.separator(); +// ui.separator(); - ui.label("Connect to an existing game:"); - ui.horizontal(|ui| { - ui.label("Game ID: "); - ui.text_edit_singleline(&mut *connection_string); +// ui.label("Name"); +// ui.text_edit_singleline(&mut *name); - let Ok(game_id) = Uuid::parse_str(&connection_string) else { - return; - }; +// ui.separator(); - if ui.button("Join").clicked() { - next_scene.set(CurrentScene::Lobby); - request_join.send(SendTo( - game_id, - RequestJoin(Player { - name: name.clone(), - rank: PlayerRank::Player, - uuid, - color: rand::random::<(u8, u8, u8)>(), - }), - )); - } - }); +// ui.label("Connect to an existing game:"); +// ui.horizontal(|ui| { +// ui.label("Game ID: "); +// ui.text_edit_singleline(&mut *connection_string); - ui.separator(); +// let Ok(game_id) = Uuid::parse_str(&connection_string) else { +// return; +// }; - if ui.button("Create new game").clicked() { - next_scene.set(CurrentScene::Lobby); - commands.spawn(Player { - name: name.clone(), - rank: PlayerRank::Admin, - uuid, - color: rand::random::<(u8, u8, u8)>(), - }); - } - }); +// if ui.button("Join").clicked() { +// next_scene.set(CurrentScene::Lobby); +// request_join.send(SendTo( +// game_id, +// RequestJoin(Player { +// name: name.clone(), +// rank: PlayerRank::Player, +// uuid, +// color: rand::random::<(u8, u8, u8)>(), +// }), +// )); +// } +// }); + +// ui.separator(); + +// if ui.button("Create new game").clicked() { +// next_scene.set(CurrentScene::Lobby); +// commands.spawn(Player { +// name: name.clone(), +// rank: PlayerRank::Admin, +// uuid, +// color: rand::random::<(u8, u8, u8)>(), +// }); +// } +// }); +// } + +/// A Component to identify menus entities. +/// In order to be able to remove them later. +#[derive(Component)] +struct MenuEntity; + +type TargetScene = crate::Scene; + +/// Create main element for the menu +fn menu_ui(mut commands: Commands, asset_server: Res) { + // Create the background. + commands + .spawn(ImageBundle { + style: Style { + margin: UiRect::all(Val::Auto), + width: px(1280.), + height: px(720.), + flex_direction: FlexDirection::Column, + ..default() + }, + image: asset_server.load("menu/bw_menu_bg.png").into(), + z_index: ZIndex::Local(0), + ..default() + }) + .insert(MenuEntity) + .with_children(|child: &mut ChildBuilder| creation_menu_ui(child, &asset_server)); + + // Create the settings button. + create_side_button( + UiRect { + left: px(25.), + right: Val::Auto, + top: px(25.), + bottom: Val::Auto, + }, + TargetScene::Lobby, + &mut commands, + HoveredTexture { + texture: asset_server.load("menu/setting.png"), + hovered_texture: asset_server.load("menu/setting_hover.png"), + }, + ); + + // Create the info button. + create_side_button( + UiRect { + left: Val::Auto, + right: px(25.), + top: px(25.), + bottom: Val::Auto, + }, + TargetScene::Lobby, + &mut commands, + HoveredTexture { + texture: asset_server.load("menu/info.png"), + hovered_texture: asset_server.load("menu/info_hover.png"), + }, + ); +} + +/// A function to create a side button. +fn create_side_button( + margin: UiRect, + target_scene: TargetScene, + commands: &mut Commands, + textures: HoveredTexture, +) { + commands + .spawn(ButtonBundle { + style: Style { + width: px(53.), + aspect_ratio: Some(1.), + margin, + ..default() + }, + z_index: ZIndex::Global(14), + image: textures.texture.clone().into(), + ..default() + }) + .insert((target_scene, textures, MenuEntity)); +} + +/// That function create all elements of the menu. +fn creation_menu_ui(commands: &mut ChildBuilder, asset_server: &Res) { + // Create the title. + create_object( + commands, + (UiImage { + texture: asset_server.load("menu/border_wars.png"), + ..default() + },), + (px(614.), px(78.)), + (px(333.), px(25.)), + ); + + // Create the host icon. + create_object( + commands, + (UiImage { + texture: asset_server.load("menu/host_icon.png"), + ..default() + },), + (px(53.), px(42.)), + (px(356.), px(223.)), + ); + + // Create the host title. + create_object( + commands, + (UiImage { + texture: asset_server.load("menu/host.png"), + ..default() + },), + (px(105.), px(38.)), + (px(429.), px(229.)), + ); + + // Create the host line. + create_object( + commands, + (UiImage { + texture: asset_server.load("menu/line.png"), + ..default() + },), + (px(427.), px(7.)), + (px(426.), px(279.)), + ); + + // Create the host button. + create_object( + commands, + ( + UiImage { + texture: asset_server.load("menu/button.png"), + ..default() + }, + Button, + Host, + ), + (px(253.), px(34.)), + (px(513.), px(299.)), + ); + + // Create the join icon. + create_object( + commands, + (UiImage { + texture: asset_server.load("menu/join_icon.png"), + ..default() + },), + (px(63.), px(41.)), + (px(353.), px(393.)), + ); + + // Create the join title. + create_object( + commands, + (UiImage { + texture: asset_server.load("menu/join.png"), + ..default() + },), + (px(101.), px(38.)), + (px(428.), px(392.)), + ); + + // Create the join line. + create_object( + commands, + (UiImage { + texture: asset_server.load("menu/line.png"), + ..default() + },), + (px(427.), px(7.)), + (px(426.), px(443.)), + ); + + // Create the join button. + create_object( + commands, + ( + UiImage { + texture: asset_server.load("menu/button.png"), + ..default() + }, + Button, + Join, + ), + (px(253.), px(34.)), + (px(513.), px(463.)), + ); + + // Create the airplane. + create_object( + commands, + ( + UiImage { + texture: asset_server.load("menu/airplane.png"), + ..default() + }, + Button, + ), + (px(35.), px(30.)), + (px(777.), px(465.)), + ); +} + +/// A function that create objets with the given parameters. +fn create_object( + background: &mut ChildBuilder, + bundle: T, + size: (Val, Val), + pos: (Val, Val), +) { + background + .spawn(ImageBundle { + style: Style { + width: size.0, + height: size.1, + left: pos.0, + top: pos.1, + position_type: PositionType::Absolute, + ..default() + }, + ..default() + }) + .insert(bundle); +} + +/// Translate a f32 into a `Val::Px'. +fn px(value: f32) -> Val { + Val::Px(value) }