move menu work, start on preliminary save system

This commit is contained in:
2026-08-21 01:20:22 -05:00
parent f4d803eb35
commit 7bf458c3cc
5 changed files with 350 additions and 21 deletions
+110 -19
View File
@@ -1,4 +1,8 @@
use crate::save::get_saves;
use crate::{AppState, WINDOW_TARGET_HEIGHT, WINDOW_TARGET_WIDTH};
use bevy::color::palettes::tailwind::SLATE_900;
use bevy::input_focus::tab_navigation::TabIndex;
use bevy::text::{EditableText, TextCursorStyle};
use bevy::ui_widgets::Button;
use bevy::{prelude::*, ui_widgets::Activate};
use derive_more::{Deref, DerefMut};
@@ -9,6 +13,7 @@ impl Plugin for MainMenuPlugin {
fn build(&self, app: &mut App) {
app.add_systems(OnEnter(AppState::Menu), setup_menu)
.add_systems(OnExit(AppState::Menu), cleanup_menu)
// .add_systems(Startup, enable_ui_debug)
.add_systems(Update, (menu_redraw).run_if(in_state(AppState::Menu)))
.add_observer(button_activate_observer)
.add_systems(Update, (scale_ui, style_ui_elements));
@@ -78,6 +83,7 @@ pub enum MenuLayer {
Root,
Play,
LoadSave,
NewGame,
Browse,
DirectConnect,
Settings,
@@ -110,16 +116,31 @@ impl MenuLayer {
menu_button("Direct Connect", Some(MenuLayer::DirectConnect)),
]
}),
MenuLayer::LoadSave => Box::new(bsn! {
menu_layer(layer)
MenuLayer::LoadSave => {
// TODO: this needs to be on an IO thread
let saves = get_saves().unwrap_or_default();
let entries: Vec<_> = saves
.into_iter()
.map(|m| menu_button(m.save_name, None))
.collect();
Box::new(bsn! {
menu_layer(layer)
ChildOf(menu_root)
Children [
{entries}
(
menu_button("New Game", Some(MenuLayer::NewGame))
InteractionColors::GOOD
),
]
})
}
MenuLayer::NewGame => Box::new(bsn! {
full_menu_layer(layer)
ChildOf(menu_root)
Children [
menu_button("Save 1", None),
menu_button("Save 2", None),
(
menu_button("New Game", None)
InteractionColors::GOOD
),
{new_game_menu()}
]
}),
MenuLayer::Browse => Box::new(bsn! {
@@ -170,6 +191,13 @@ struct LastMenu(Vec<MenuLayer>);
#[derive(Resource, Debug, Clone, PartialEq, Eq, Hash, Deref, DerefMut)]
struct CurrentMenu(Vec<MenuLayer>);
// fn enable_ui_debug(mut debug_options: ResMut<GlobalUiDebugOptions>) {
// debug_options.enabled = true;
// debug_options.outline_border_box = true;
// debug_options.outline_padding_box = true;
// debug_options.outline_content_box = true;
// }
fn setup_menu(mut commands: Commands) {
commands.insert_resource(CurrentMenu(vec![MenuLayer::Root]));
commands.insert_resource(LastMenu(vec![]));
@@ -233,6 +261,70 @@ fn menu_redraw(
}
}
fn new_game_menu() -> impl SceneList {
bsn_list![
(
Text("New Game")
Node {
align_self: AlignSelf::Center,
}
TextFont {
// font: FontSourceTemplate::Handle("fonts/FiraSans-Bold.ttf"),
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
),
(
#NewGameTextField
Node {
border: Val::all(px(6)),
padding: Val::all(px(12)),
border_radius: BorderRadius::all(px(12)),
}
// BorderColor::from(SLATE_800)
BorderColor::from(SLATE_900)
EditableText {
cursor_width: 0.05,
}
TextLayout::no_wrap()
TextFont {
font_size: FontSize::Px(66.),
}
TextCursorStyle {
color: Color::BLACK
}
TabIndex(0)
BackgroundColor(Color::srgb(0.48, 0.84, 0.87))
),
(
Node {
margin: UiRect::top(px(48)),
}
Children [
menu_button("Create", None)
Node {
margin: UiRect::left(Val::Auto),
}
InteractionColors::GOOD
on(|event: On<Activate>, q_text:| { info!("create!") })
]
),
]
}
fn menu_layer(layer: usize) -> impl Scene {
let name = format!("MenuLayer{}", layer);
bsn! {
@@ -242,8 +334,6 @@ fn menu_layer(layer: usize) -> impl Scene {
width: percent(100.0 / N_LAYERS as f32),
height: percent(100),
flex_direction: FlexDirection::Column,
// align_items: AlignItems::Start,
align_items: AlignItems::Baseline,
justify_content: JustifyContent::FlexEnd,
row_gap: px(100),
}
@@ -251,21 +341,22 @@ fn menu_layer(layer: usize) -> impl Scene {
}
fn full_menu_layer(layer: usize) -> impl Scene {
let name = format!("FullMenuLayer{}", layer);
bsn! {
menu_layer(layer)
Name(name)
Layer(layer)
Node {
width: Val::Auto,
flex_direction: FlexDirection::Column,
align_self: AlignSelf::FlexEnd,
flex_grow: 1.,
border_radius: BorderRadius::all(px(24)),
padding: Val::all(px(24)),
}
BackgroundColor(Color::srgba(0.8, 0.1, 0.1, 0.7))
BackgroundColor(Color::srgb(0.4, 0.4, 0.4))
}
}
fn menu_button(label: &str, next_layer: Option<MenuLayer>) -> impl Scene {
let next_layer_component = next_layer
.map(|n| Box::new(bsn! { NextLayer(n) }) as Box<dyn Scene>)
.unwrap_or(Box::new(bsn! {}));
fn menu_button(label: impl Into<String>, next_layer: Option<MenuLayer>) -> impl Scene {
bsn! {
Button
Node {
@@ -277,7 +368,7 @@ fn menu_button(label: &str, next_layer: Option<MenuLayer>) -> impl Scene {
align_items: AlignItems::Center,
margin: UiRect::all(px(4)),
}
next_layer_component
{next_layer.map(|l| template_value(NextLayer(l)))}
BorderColor::from(Color::BLACK)
InteractionColors::DEFAULT
Interaction