work on lobby ui
This commit is contained in:
+111
-36
@@ -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),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user