diff --git a/Cargo.toml b/Cargo.toml index 8932293..c500d5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] app_dirs2 = "2.5.5" -bevy = { version = "0.19", features = ["system_clipboard"] } +bevy = { version = "0.19", features = ["system_clipboard", "debug"] } derive_more = { version = "2.1.1", features = ["deref", "deref_mut"] } jiff = { version = "0.2.35", features = ["serde"] } ron = "0.12.2" diff --git a/src/lobby.rs b/src/lobby.rs new file mode 100644 index 0000000..411d27a --- /dev/null +++ b/src/lobby.rs @@ -0,0 +1,214 @@ +use bevy::{ + color::palettes::tailwind::SLATE_900, + input_focus::tab_navigation::TabIndex, + prelude::*, + text::{EditableText, EditableTextFilter, TextCursorStyle}, + ui_widgets::{RadioButton, RadioGroup}, +}; + +use crate::AppState; + +pub struct LobbyPlugin; + +impl Plugin for LobbyPlugin { + fn build(&self, app: &mut App) { + app.add_systems( + OnEnter(AppState::Lobby), + (setup_lobby, build_lobby_ui).chain(), + ); + } +} + +/// The root of the lobby ui. +#[derive(Component, Debug, Copy, Clone, Default, PartialEq, Eq, Hash)] +struct LobbyUiRoot; + +fn setup_lobby(mut commands: Commands) { + commands.spawn_scene(bsn! { + #LobbyUiRoot + LobbyUiRoot + DespawnOnExit::(AppState::Lobby) + Node { + width: percent(100), + height: percent(100), + flex_direction: FlexDirection::Row, + column_gap: px(24), + padding: Val::all(px(24)), + } + }); +} + +fn build_lobby_ui(mut commands: Commands, root_ui: Single>) { + let root_ui = *root_ui; + + commands.spawn_scene(bsn! { + ChildOf(root_ui) + Node { + flex_direction: FlexDirection::Column, + align_self: AlignSelf::FlexEnd, + flex_grow: 1., + border_radius: BorderRadius::all(px(24)), + padding: Val::all(px(24)), + } + BackgroundColor(Color::srgb(0.4, 0.4, 0.4)) + Children [ + ( + Text("Server Settings") + Node { + align_self: AlignSelf::Center, + } + TextFont { + font_size: px(100.0), + } + TextColor(Color::srgb(0.9, 0.9, 0.9)) + TextShadow + ), + ( + RadioGroup + Node { + display: Display::Flex, + flex_direction: FlexDirection::Column, + align_items: AlignItems::Start, + column_gap: px(4), + } + Children [ + radio_button(), + ] + ), + ( + Text("Save Name") + Node { + margin: UiRect::axes(px(12), px(0)), + } + TextFont { + // font: FontSourceTemplate::Handle("fonts/FiraSans-Bold.ttf"), + font_size: px(66.0), + } + TextColor(Color::srgb(0.9, 0.9, 0.9)) + TextShadow + ), + ( + Node { + border: Val::all(px(6)), + padding: Val::all(px(12)), + border_radius: BorderRadius::all(px(12)), + } + BorderColor::from(SLATE_900) + EditableText { + cursor_width: 0.05, + max_characters: Option::Some(14), + } + EditableTextFilter::new(|c| c == ' ' || c.is_ascii_alphanumeric()) + TextLayout::no_wrap() + TextFont { + font_size: FontSize::Px(66.), + } + TextCursorStyle { + color: Color::BLACK + } + TabIndex(0) + BackgroundColor(Color::srgb(0.48, 0.84, 0.87)) + ), + ] + }); + commands.spawn_scene(bsn! { + ChildOf(root_ui) + Node { + flex_direction: FlexDirection::Column, + align_self: AlignSelf::FlexEnd, + flex_grow: 1., + border_radius: BorderRadius::all(px(24)), + padding: Val::all(px(24)), + } + BackgroundColor(Color::srgb(0.4, 0.4, 0.4)) + Children [ + ( + Text("Lobby") + Node { + align_self: AlignSelf::Center, + } + TextFont { + font_size: px(100.0), + } + TextColor(Color::srgb(0.9, 0.9, 0.9)) + TextShadow + ), + ( + Text("Save Name") + Node { + margin: UiRect::axes(px(12), px(0)), + } + TextFont { + // font: FontSourceTemplate::Handle("fonts/FiraSans-Bold.ttf"), + font_size: px(66.0), + } + TextColor(Color::srgb(0.9, 0.9, 0.9)) + TextShadow + ), + ( + Node { + border: Val::all(px(6)), + padding: Val::all(px(12)), + border_radius: BorderRadius::all(px(12)), + } + BorderColor::from(SLATE_900) + EditableText { + cursor_width: 0.05, + max_characters: Option::Some(14), + } + EditableTextFilter::new(|c| c == ' ' || c.is_ascii_alphanumeric()) + TextLayout::no_wrap() + TextFont { + font_size: FontSize::Px(66.), + } + TextCursorStyle { + color: Color::BLACK + } + TabIndex(0) + BackgroundColor(Color::srgb(0.48, 0.84, 0.87)) + ), + ] + }); +} + +fn radio_button() -> impl Scene { + bsn! { + RadioButton + Node { + display: Display::Flex, + flex_direction: FlexDirection::Row, + justify_content: JustifyContent::FlexStart, + align_items: AlignItems::Center, + align_content: AlignContent::Center, + column_gap: px(8), + } + Children [ + #RadioOuter + Node { + display: Display::Flex, + width: px(32), + height: px(32), + border: UiRect::all(px(4)), + border_radius: BorderRadius::MAX, + } + BorderColor::all(Color::BLACK) + Children [ + #RadioInner + Node { + display: Display::Flex, + width: px(16), + height: px(16), + position_type: PositionType::Absolute, + left: px(4), + top: px(4), + border_radius: BorderRadius::MAX, + } + BackgroundColor(Color::srgb(0.35, 0.75, 0.35)) + ], + Text::new("Radio Button") + TextFont { + font_size: FontSize::Px(33.0), + } + ] + } +} diff --git a/src/main.rs b/src/main.rs index 209f2dd..a37ce8e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,8 +2,9 @@ use bevy::{camera::ScalingMode, color::palettes::css::GREEN, prelude::*}; use main_menu::MainMenuPlugin; use networking::NetworkingPlugin; -use crate::save::SavePlugin; +use crate::{lobby::LobbyPlugin, save::SavePlugin}; +mod lobby; mod main_menu; mod networking; mod save; @@ -28,7 +29,13 @@ pub enum AppState { fn main() { App::new() - .add_plugins((DefaultPlugins, MainMenuPlugin, NetworkingPlugin, SavePlugin)) + .add_plugins(( + DefaultPlugins, + MainMenuPlugin, + NetworkingPlugin, + SavePlugin, + LobbyPlugin, + )) .add_systems(Startup, setup) .add_systems(Update, debug_border) .insert_resource(ClearColor(Color::srgb(0.07, 0.33, 0.45))) diff --git a/src/main_menu.rs b/src/main_menu.rs index 5f3f738..95749ec 100644 --- a/src/main_menu.rs +++ b/src/main_menu.rs @@ -226,8 +226,6 @@ fn setup_menu(mut commands: Commands) { width: percent(90), height: percent(70), margin: UiRect::AUTO, - align_items: AlignItems::Start, - justify_content: JustifyContent::Start, column_gap: px(10), } });