work on lobby ui

This commit is contained in:
2026-09-17 15:59:47 -05:00
parent b041075c09
commit df95653b86
5 changed files with 605 additions and 43 deletions
+111 -36
View File
@@ -3,19 +3,53 @@ use bevy::{
input_focus::tab_navigation::TabIndex,
prelude::*,
text::{EditableText, EditableTextFilter, TextCursorStyle},
ui_widgets::{RadioButton, RadioGroup},
ui::{Checked, Pressed},
ui_widgets::{RadioButton, RadioGroup, ValueChange, radio_self_update},
};
use crate::AppState;
pub struct LobbyPlugin;
#[derive(Resource, Debug, Clone, Copy, PartialEq, Eq, Reflect)]
#[reflect(Resource)]
pub struct LobbyUiState {
pub visibility: LobbyVisibility,
}
impl Default for LobbyUiState {
fn default() -> Self {
Self {
visibility: LobbyVisibility::Public,
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Reflect)]
pub enum LobbyVisibility {
#[default]
Public,
FriendsOnly,
InviteOnly,
}
#[derive(Component, Debug, Clone, Copy, Default, PartialEq, Eq)]
struct LobbyVisibilityOption(LobbyVisibility);
impl Plugin for LobbyPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<LobbyUiState>();
app.register_type::<LobbyUiState>();
app.add_systems(
OnEnter(AppState::Lobby),
(setup_lobby, build_lobby_ui).chain(),
)
.add_systems(
Update,
(sync_visibility_options, style_visibility_options).chain(),
);
app.add_observer(radio_self_update);
app.add_observer(on_visibility_changed);
}
}
@@ -67,12 +101,15 @@ fn build_lobby_ui(mut commands: Commands, root_ui: Single<Entity, With<LobbyUiRo
RadioGroup
Node {
display: Display::Flex,
flex_direction: FlexDirection::Column,
align_items: AlignItems::Start,
column_gap: px(4),
flex_direction: FlexDirection::Row,
width: px(900),
height: px(110),
}
TabIndex(0)
Children [
radio_button(),
visibility_option("Public", LobbyVisibility::Public, BorderRadius::px(16., 0., 0., 16.)),
visibility_option("Friends Only", LobbyVisibility::FriendsOnly, BorderRadius::ZERO),
visibility_option("Invite Only", LobbyVisibility::InviteOnly, BorderRadius::px(0., 16., 16., 0.)),
]
),
(
@@ -171,44 +208,82 @@ fn build_lobby_ui(mut commands: Commands, root_ui: Single<Entity, With<LobbyUiRo
});
}
fn radio_button() -> impl Scene {
fn visibility_option(
label: &'static str,
visibility: LobbyVisibility,
border_radius: BorderRadius,
) -> impl Scene {
bsn! {
RadioButton
LobbyVisibilityOption(visibility)
Node {
display: Display::Flex,
flex_direction: FlexDirection::Row,
justify_content: JustifyContent::FlexStart,
flex_grow: 1.,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
align_content: AlignContent::Center,
column_gap: px(8),
border: UiRect::all(px(3)),
border_radius,
}
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")
BorderColor::all(Color::srgb(0.12, 0.16, 0.22))
BackgroundColor(Color::srgb(0.18, 0.22, 0.29))
Children [(
Text(label)
TextFont {
font_size: FontSize::Px(33.0),
font_size: px(38.0),
}
]
TextColor(Color::srgb(0.92, 0.94, 0.98))
)]
}
}
fn sync_visibility_options(
lobby_ui: Res<LobbyUiState>,
mut commands: Commands,
options: Query<
(Entity, &LobbyVisibilityOption),
(With<RadioButton>, Added<LobbyVisibilityOption>),
>,
) {
for (entity, option) in &options {
if option.0 == lobby_ui.visibility {
commands.entity(entity).insert(Checked);
} else {
commands.entity(entity).remove::<Checked>();
}
}
}
fn on_visibility_changed(
value_change: On<ValueChange<Entity>>,
options: Query<&LobbyVisibilityOption>,
mut lobby_ui: ResMut<LobbyUiState>,
) {
if let Ok(option) = options.get(value_change.value) {
lobby_ui.visibility = option.0;
}
}
fn style_visibility_options(
mut options: Query<
(
&Interaction,
Has<Checked>,
Has<Pressed>,
&mut BackgroundColor,
),
(
With<LobbyVisibilityOption>,
// Or<(Changed<Interaction>, Changed<Checked>, Changed<Pressed>)>,
),
>,
) {
for (interaction, checked, pressed, mut background) in &mut options {
background.0 = match (checked, pressed, *interaction) {
(true, true, _) => Color::srgb(0.08, 0.48, 0.58),
(true, _, Interaction::Hovered) => Color::srgb(0.10, 0.58, 0.68),
(true, _, _) => Color::srgb(0.08, 0.42, 0.52),
(false, _, Interaction::Hovered) => Color::srgb(0.26, 0.33, 0.42),
(false, _, _) => Color::srgb(0.18, 0.22, 0.29),
};
}
}