diff --git a/src/tile.rs b/src/tile.rs index 40879fe..c0941d4 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -1,7 +1,7 @@ use bevy::{ecs::entity::MapEntities, prelude::*}; use strum::FromRepr; -#[derive(Component, Debug)] +#[derive(Component, Debug, Clone, Copy)] pub struct Tile { pub suit: Suit, } diff --git a/src/tui/console.rs b/src/tui/console.rs index f668331..2390c5e 100644 --- a/src/tui/console.rs +++ b/src/tui/console.rs @@ -1,6 +1,6 @@ use bevy::prelude::*; use bevy_ratatui::RatatuiContext; -use ratatui::widgets::Block; +use ratatui::{layout::Margin, widgets::Block}; use tui_logger::TuiLoggerWidget; #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)] @@ -24,7 +24,10 @@ impl std::ops::Not for ConsoleState { pub(crate) fn draw_console(mut tui_ctx: ResMut) -> Result { tui_ctx.draw(|frame| { let block = Block::bordered().title("console"); - frame.render_widget(TuiLoggerWidget::default().block(block), frame.area()); + frame.render_widget( + TuiLoggerWidget::default().block(block), + frame.area(), /* .inner(Margin { horizontal: 8, vertical: 8 }) */ + ); })?; Ok(()) diff --git a/src/tui/input/keyboard.rs b/src/tui/input/keyboard.rs index ee77c1a..2a5e760 100644 --- a/src/tui/input/keyboard.rs +++ b/src/tui/input/keyboard.rs @@ -4,7 +4,7 @@ use bevy_ratatui::event::KeyMessage; use jong::game::GameState; -use crate::tui::{TuiState, console::ConsoleState}; +use crate::tui::{TuiState, ZenState, console::ConsoleState}; // TODO change this to handle console open request, esc for menu, etc, then // route other messages to other systems @@ -16,10 +16,12 @@ pub(crate) fn input_system( curr_tuistate: Res>, curr_consolestate: Res>, curr_gamestate: Res>, + curr_zenstate: Res>, mut next_tuistate: ResMut>, mut next_consolestate: ResMut>, mut next_gamestate: ResMut>, + mut next_zenstate: ResMut>, mut exit: MessageWriter, ) { @@ -58,6 +60,10 @@ pub(crate) fn input_system( next_tuistate.set(TuiState::InGame); next_gamestate.set(GameState::Setup); } + KeyCode::Char('z') => match curr_zenstate.get() { + ZenState::Menu => next_zenstate.set(ZenState::Zen), + ZenState::Zen => next_zenstate.set(ZenState::Menu), + }, KeyCode::Char('q') => { exit.write_default(); } diff --git a/src/tui/menu.rs b/src/tui/menu.rs index f004f41..c1c455c 100644 --- a/src/tui/menu.rs +++ b/src/tui/menu.rs @@ -1,20 +1,78 @@ use bevy::prelude::*; use bevy_ratatui::RatatuiContext; use ratatui::layout::Constraint; +use ratatui::layout::Flex; use ratatui::layout::Layout; +use ratatui::layout::Margin; +use ratatui::widgets::Paragraph; +use ratatui::widgets::{Block, Clear}; -const MAINMENU_OPTIONS: [&str; 2] = ["(p)lay", "(q)uit"]; +use jong::tile::Tile; + +use crate::tui::render::tile; + +const MAINMENU_OPTIONS: [&str; 2] = [ + " ██╗██████╗ ██╗ ██╗ █████╗ ██╗ ██╗██╗ +██╔╝██╔══██╗╚██╗██║ ██╔══██╗╚██╗ ██╔╝██║ +██║ ██████╔╝ ██║██║ ███████║ ╚████╔╝ ██║ +██║ ██╔═══╝ ██║██║ ██╔══██║ ╚██╔╝ ╚═╝ +╚██╗██║ ██╔╝███████╗██║ ██║ ██║ ██╗ + ╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ +", + " ██╗ ██████╗ ██╗ ██╗ ██╗██╗████████╗ ██╗ +██╔╝██╔═══██╗╚██╗██║ ██║██║╚══██╔══╝██╗██╔╝ +██║ ██║ ██║ ██║██║ ██║██║ ██║ ╚═╝██║ +██║ ██║▄▄ ██║ ██║██║ ██║██║ ██║ ██╗██║ +╚██╗╚██████╔╝██╔╝╚██████╔╝██║ ██║ ╚═╝╚██╗ + ╚═╝ ╚══▀▀═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ +", +]; pub(crate) fn draw_mainmenu(mut tui_ctx: ResMut) -> Result { let options = MAINMENU_OPTIONS; - let layout = Layout::vertical(vec![Constraint::Min(1); options.len()]); + let layout = + Layout::vertical(vec![Constraint::Fill(1); options.len()]).flex(Flex::SpaceBetween); + let block = Block::bordered(); tui_ctx.draw(|frame| { - let areas = layout.split(frame.area()); + let area = frame + .area() + .centered(Constraint::Max(55), Constraint::Max(19)); + frame.render_widget(Clear, area); + frame.render_widget(block, area); + let areas = layout.split(area.centered(Constraint::Max(45), Constraint::Max(14))); for (opt, area) in options.into_iter().zip(areas.iter()) { - frame.render_widget(opt, *area) + let para = Paragraph::new(opt); + frame.render_widget(para, *area) } })?; Ok(()) } + +pub(crate) fn draw_splash(mut tui_ctx: ResMut, tiles: Populated<&Tile>) -> Result { + let mut tile_it = tiles.into_iter().cycle(); + + tui_ctx.draw(|frame| { + let area = frame.area().outer(Margin { + horizontal: 1, + vertical: 1, + }); + let layout = Layout::horizontal(vec![Constraint::Max(5); (area.width / 5) as usize]); + let areas = layout.split(area); + for area in areas.iter() { + let layout = Layout::vertical(vec![Constraint::Max(4); (area.height / 4) as usize]); + let areas = layout.split(*area); + let tiles: Vec<_> = tile_it + .clone() + .take((area.height / 4 + 1) as usize) + .cloned() + .map(|t| tile::draw_tile(&t)) + .collect(); + for (tile, area) in tiles.iter().zip(areas.into_iter()) { + frame.render_widget(tile, *area); + } + } + })?; + Ok(()) +} diff --git a/src/tui/mod.rs b/src/tui/mod.rs index 69c182a..f3d95e8 100644 --- a/src/tui/mod.rs +++ b/src/tui/mod.rs @@ -27,12 +27,20 @@ impl ComputedStates for InGame { fn compute(sources: Self::SourceStates) -> Option { match sources { - TuiState::MainMenu => None, TuiState::InGame => Some(Self), + _ => None, } } } +#[derive(SubStates, Default, Clone, Copy, PartialEq, Eq, Hash, Debug,)] +#[source(TuiState = TuiState::MainMenu)] +pub(crate) enum ZenState { + #[default] + Menu, + Zen, +} + #[derive(Default)] pub struct RiichiTui; impl Plugin for RiichiTui { @@ -61,7 +69,9 @@ impl Plugin for RiichiTui { .add_systems(PreUpdate, input::mouse::input_system.chain()) // main menu - .add_systems(Update, menu::draw_mainmenu.run_if(in_state(TuiState::MainMenu))) + .add_sub_state::() + .add_systems(Update, menu::draw_splash.run_if(in_state(TuiState::MainMenu))) + .add_systems(Update, menu::draw_mainmenu.after(menu::draw_splash).run_if(in_state(TuiState::MainMenu).and(in_state(ZenState::Menu)))) // gaming .init_resource::()