generated from GarandPLG/rust-flake-template
Lazy init game states and extract board module
App now stores CLI arguments and an optional GameStates, initializing the states lazily on the first window resize. Skirmish board logic is moved to a new BoardState module with dedicated helpers (cells_area_helper and updated cell size handling). Views and keybindings are updated to use the optional state accessors.
This commit is contained in:
+15
-5
@@ -22,22 +22,29 @@ pub struct App {
|
|||||||
pub exit: bool,
|
pub exit: bool,
|
||||||
pub view: View,
|
pub view: View,
|
||||||
pub window_area: Rect,
|
pub window_area: Rect,
|
||||||
pub states: GameStates,
|
pub args: Cli,
|
||||||
|
pub states: Option<GameStates>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn new(args: Cli) -> Self {
|
pub fn new(args: Cli) -> Self {
|
||||||
let mut states: GameStates = GameStates::new(&args);
|
|
||||||
states.skirmish.init_board();
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
exit: false,
|
exit: false,
|
||||||
view: args.view,
|
view: args.view,
|
||||||
window_area: Rect::default(),
|
window_area: Rect::default(),
|
||||||
states,
|
args: args,
|
||||||
|
states: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn states(&self) -> Option<&GameStates> {
|
||||||
|
self.states.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn states_mut(&mut self) -> Option<&mut GameStates> {
|
||||||
|
self.states.as_mut()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, terminal: &mut DefaultTerminal, rx: Receiver<Event>) -> Result<()> {
|
pub fn run(&mut self, terminal: &mut DefaultTerminal, rx: Receiver<Event>) -> Result<()> {
|
||||||
while !self.exit {
|
while !self.exit {
|
||||||
terminal.draw(|frame: &mut Frame<'_>| self.draw(frame))?;
|
terminal.draw(|frame: &mut Frame<'_>| self.draw(frame))?;
|
||||||
@@ -65,6 +72,9 @@ impl App {
|
|||||||
|| window_area.height != self.window_area.height
|
|| window_area.height != self.window_area.height
|
||||||
{
|
{
|
||||||
self.window_area = window_area;
|
self.window_area = window_area;
|
||||||
|
if self.states.is_none() {
|
||||||
|
self.states = Some(GameStates::new(&self.args, &self.window_area))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.render_widget(self, window_area);
|
frame.render_widget(self, window_area);
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
use crate::app::views::skirmish_layout;
|
||||||
|
use ratatui::{
|
||||||
|
layout::{Margin, Rect},
|
||||||
|
widgets::{Block, Borders},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn cells_area_helper(area: &Rect) -> Rect {
|
||||||
|
Block::new()
|
||||||
|
.borders(Borders::LEFT | Borders::TOP | Borders::RIGHT)
|
||||||
|
.inner(skirmish_layout(*area)[1])
|
||||||
|
.inner(Margin {
|
||||||
|
horizontal: 3,
|
||||||
|
vertical: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
pub mod block_title;
|
pub mod block_title;
|
||||||
|
pub mod cells_area;
|
||||||
pub mod main_menu_option;
|
pub mod main_menu_option;
|
||||||
pub mod zoom_level;
|
pub mod zoom_level;
|
||||||
|
|
||||||
pub use block_title::{block_single_title_helper, block_title_helper};
|
pub use block_title::{block_single_title_helper, block_title_helper};
|
||||||
|
pub use cells_area::cells_area_helper;
|
||||||
pub use main_menu_option::main_menu_option_helper;
|
pub use main_menu_option::main_menu_option_helper;
|
||||||
pub use zoom_level::{CellSizes, cell_size_helper};
|
pub use zoom_level::{CellSizes, cell_size_helper};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ pub enum CellSizes {
|
|||||||
Height,
|
Height,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cell_size_helper(cell_size: CellSizes, zoom_level: ZoomLevel) -> u16 {
|
pub fn cell_size_helper(cell_size: CellSizes, zoom_level: ZoomLevel) -> usize {
|
||||||
match (cell_size, zoom_level) {
|
match (cell_size, zoom_level) {
|
||||||
(CellSizes::Width, ZoomLevel::ZoomedIn) => 13,
|
(CellSizes::Width, ZoomLevel::ZoomedIn) => 13,
|
||||||
(CellSizes::Width, ZoomLevel::Default) => 9,
|
(CellSizes::Width, ZoomLevel::Default) => 9,
|
||||||
|
|||||||
@@ -7,17 +7,22 @@ use ratatui::crossterm::event::KeyEvent;
|
|||||||
pub fn main_menu_keybindings(app: &mut App, event: &KeyEvent) {
|
pub fn main_menu_keybindings(app: &mut App, event: &KeyEvent) {
|
||||||
if let Some(action) = event_to_action(&event) {
|
if let Some(action) = event_to_action(&event) {
|
||||||
common_keybindings(app, action);
|
common_keybindings(app, action);
|
||||||
|
|
||||||
|
let Some(states) = app.states_mut() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
Action::Up => {
|
Action::Up => {
|
||||||
app.states.main_menu.selected_view =
|
states.main_menu.selected_view =
|
||||||
app.states.main_menu.selected_view.saturating_sub(1).max(1);
|
states.main_menu.selected_view.saturating_sub(1).max(1);
|
||||||
}
|
}
|
||||||
Action::Down => {
|
Action::Down => {
|
||||||
app.states.main_menu.selected_view =
|
states.main_menu.selected_view =
|
||||||
app.states.main_menu.selected_view.saturating_add(1).min(3);
|
states.main_menu.selected_view.saturating_add(1).min(3);
|
||||||
}
|
}
|
||||||
Action::Space => {
|
Action::Space => {
|
||||||
let selected_view: usize = app.states.main_menu.selected_view;
|
let selected_view: usize = states.main_menu.selected_view;
|
||||||
|
|
||||||
if selected_view == 1 {
|
if selected_view == 1 {
|
||||||
app.view = View::Skirmish;
|
app.view = View::Skirmish;
|
||||||
|
|||||||
@@ -8,48 +8,53 @@ use ratatui::crossterm::event::KeyEvent;
|
|||||||
pub fn skirmish_keybindings(app: &mut App, key_event: &KeyEvent) {
|
pub fn skirmish_keybindings(app: &mut App, key_event: &KeyEvent) {
|
||||||
if let Some(action) = event_to_action(&key_event) {
|
if let Some(action) = event_to_action(&key_event) {
|
||||||
common_keybindings(app, action);
|
common_keybindings(app, action);
|
||||||
|
|
||||||
|
let Some(states) = app.states_mut() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
Action::Up => app.states.skirmish.focused_cell.move_up(),
|
Action::Up => states.skirmish.board.focused_cell.move_up(),
|
||||||
Action::Down => app.states.skirmish.focused_cell.move_down(),
|
Action::Down => states.skirmish.board.focused_cell.move_down(),
|
||||||
Action::Left => app.states.skirmish.focused_cell.move_left(),
|
Action::Left => states.skirmish.board.focused_cell.move_left(),
|
||||||
Action::Right => app.states.skirmish.focused_cell.move_right(),
|
Action::Right => states.skirmish.board.focused_cell.move_right(),
|
||||||
Action::ScrollUp => {
|
Action::ScrollUp => {
|
||||||
app.states.skirmish.vertical_offset.prev();
|
states.skirmish.board.vertical_offset.prev();
|
||||||
app.states.skirmish.focused_cell.move_up();
|
states.skirmish.board.focused_cell.move_up();
|
||||||
}
|
}
|
||||||
Action::ScrollDown => {
|
Action::ScrollDown => {
|
||||||
app.states.skirmish.vertical_offset.next();
|
states.skirmish.board.vertical_offset.next();
|
||||||
app.states.skirmish.focused_cell.move_down();
|
states.skirmish.board.focused_cell.move_down();
|
||||||
}
|
}
|
||||||
Action::ScrollLeft => {
|
Action::ScrollLeft => {
|
||||||
app.states.skirmish.horizontal_offset.prev();
|
states.skirmish.board.horizontal_offset.prev();
|
||||||
app.states.skirmish.focused_cell.move_left();
|
states.skirmish.board.focused_cell.move_left();
|
||||||
}
|
}
|
||||||
Action::ScrollRight => {
|
Action::ScrollRight => {
|
||||||
app.states.skirmish.horizontal_offset.next();
|
states.skirmish.board.horizontal_offset.next();
|
||||||
app.states.skirmish.focused_cell.move_right();
|
states.skirmish.board.focused_cell.move_right();
|
||||||
}
|
}
|
||||||
Action::ZoomIn => match app.states.skirmish.zoom_level {
|
Action::ZoomIn => match states.skirmish.board.zoom_level {
|
||||||
ZoomLevel::ZoomedIn => {}
|
ZoomLevel::ZoomedIn => {}
|
||||||
ZoomLevel::Default => {
|
ZoomLevel::Default => {
|
||||||
app.states.skirmish.zoom_level = ZoomLevel::ZoomedIn;
|
states.skirmish.board.zoom_change(ZoomLevel::ZoomedIn);
|
||||||
app.states.skirmish.vertical_offset.next();
|
states.skirmish.board.vertical_offset.next();
|
||||||
}
|
}
|
||||||
ZoomLevel::ZoomedOut => {
|
ZoomLevel::ZoomedOut => {
|
||||||
app.states.skirmish.zoom_level = ZoomLevel::Default;
|
states.skirmish.board.zoom_change(ZoomLevel::Default);
|
||||||
app.states.skirmish.vertical_offset.next();
|
states.skirmish.board.vertical_offset.next();
|
||||||
app.states.skirmish.vertical_offset.next();
|
states.skirmish.board.vertical_offset.next();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Action::ZoomOut => match app.states.skirmish.zoom_level {
|
Action::ZoomOut => match states.skirmish.board.zoom_level {
|
||||||
ZoomLevel::ZoomedIn => {
|
ZoomLevel::ZoomedIn => {
|
||||||
app.states.skirmish.zoom_level = ZoomLevel::Default;
|
states.skirmish.board.zoom_change(ZoomLevel::Default);
|
||||||
app.states.skirmish.vertical_offset.prev();
|
states.skirmish.board.vertical_offset.prev();
|
||||||
}
|
}
|
||||||
ZoomLevel::Default => {
|
ZoomLevel::Default => {
|
||||||
app.states.skirmish.zoom_level = ZoomLevel::ZoomedOut;
|
states.skirmish.board.zoom_change(ZoomLevel::ZoomedOut);
|
||||||
app.states.skirmish.vertical_offset.prev();
|
states.skirmish.board.vertical_offset.prev();
|
||||||
app.states.skirmish.vertical_offset.prev();
|
states.skirmish.board.vertical_offset.prev();
|
||||||
}
|
}
|
||||||
ZoomLevel::ZoomedOut => {}
|
ZoomLevel::ZoomedOut => {}
|
||||||
},
|
},
|
||||||
|
|||||||
+8
-13
@@ -1,10 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::states::{
|
app::states::{
|
||||||
FocusedCell, MainMenuState, Offset, PerkDecksState, SettingsState, SkillsConfigState,
|
MainMenuState, PerkDecksState, SettingsState, SkillsConfigState, SkirmishState,
|
||||||
SkirmishState,
|
skirmish_states::BoardState,
|
||||||
},
|
},
|
||||||
cli::Cli,
|
cli::Cli,
|
||||||
};
|
};
|
||||||
|
use ratatui::layout::Rect;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct GameStates {
|
pub struct GameStates {
|
||||||
@@ -16,7 +17,7 @@ pub struct GameStates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GameStates {
|
impl GameStates {
|
||||||
pub fn new(args: &Cli) -> Self {
|
pub fn new(args: &Cli, area: &Rect) -> Self {
|
||||||
Self {
|
Self {
|
||||||
main_menu: MainMenuState {
|
main_menu: MainMenuState {
|
||||||
id: 0,
|
id: 0,
|
||||||
@@ -26,17 +27,11 @@ impl GameStates {
|
|||||||
skirmish: SkirmishState {
|
skirmish: SkirmishState {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "Skirmish",
|
name: "Skirmish",
|
||||||
vertical_offset: Offset::new(),
|
board: BoardState::new(
|
||||||
horizontal_offset: Offset::new(),
|
area,
|
||||||
map_width: args.map_width as usize,
|
|
||||||
map_height: args.map_height as usize,
|
|
||||||
board_cells: Vec::new(),
|
|
||||||
zoom_level: args.zoom_level,
|
|
||||||
focused_cell: FocusedCell::new(
|
|
||||||
(args.map_height / 2) as usize - 1,
|
|
||||||
2,
|
|
||||||
args.map_height as usize,
|
|
||||||
args.map_width as usize,
|
args.map_width as usize,
|
||||||
|
args.map_height as usize,
|
||||||
|
args.zoom_level,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
perk_decks: PerkDecksState {
|
perk_decks: PerkDecksState {
|
||||||
|
|||||||
@@ -1,34 +1,11 @@
|
|||||||
use crate::app::{
|
use crate::app::states::skirmish_states::BoardState;
|
||||||
states::{FocusedCell, Offset},
|
|
||||||
widgets::CellWidget,
|
|
||||||
};
|
|
||||||
use clap::ValueEnum;
|
use clap::ValueEnum;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct SkirmishState {
|
pub struct SkirmishState {
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
pub map_width: usize,
|
pub board: BoardState,
|
||||||
pub map_height: usize,
|
|
||||||
pub vertical_offset: Offset,
|
|
||||||
pub horizontal_offset: Offset,
|
|
||||||
pub board_cells: Vec<CellWidget>,
|
|
||||||
pub zoom_level: ZoomLevel,
|
|
||||||
pub focused_cell: FocusedCell,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SkirmishState {
|
|
||||||
pub fn init_board(&mut self) {
|
|
||||||
if !self.board_cells.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for row in 0..self.map_height {
|
|
||||||
for col in 0..self.map_width {
|
|
||||||
self.board_cells.push(CellWidget::new(row, col, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
use crate::app::{
|
||||||
|
helpers::{CellSizes, cell_size_helper, cells_area_helper},
|
||||||
|
states::{FocusedCell, Offset, ZoomLevel},
|
||||||
|
widgets::CellWidget,
|
||||||
|
};
|
||||||
|
use ratatui::layout::Rect;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct BoardState {
|
||||||
|
pub cells_area: Rect,
|
||||||
|
pub cell_width: usize,
|
||||||
|
pub cell_height: usize,
|
||||||
|
pub map_width: usize,
|
||||||
|
pub map_height: usize,
|
||||||
|
pub cols: usize,
|
||||||
|
pub rows: usize,
|
||||||
|
pub vertical_offset: Offset,
|
||||||
|
pub horizontal_offset: Offset,
|
||||||
|
pub cells: Vec<CellWidget>,
|
||||||
|
pub zoom_level: ZoomLevel,
|
||||||
|
pub focused_cell: FocusedCell,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BoardState {
|
||||||
|
pub fn new(area: &Rect, map_width: usize, map_height: usize, zoom_level: ZoomLevel) -> Self {
|
||||||
|
let cells_area: Rect = cells_area_helper(area);
|
||||||
|
|
||||||
|
let cell_width: usize = cell_size_helper(CellSizes::Width, zoom_level);
|
||||||
|
let cell_height: usize = cell_size_helper(CellSizes::Height, zoom_level);
|
||||||
|
|
||||||
|
let cols: usize = (cells_area.width / cell_width as u16) as usize;
|
||||||
|
let rows: usize = (cells_area.height / cell_height as u16) as usize;
|
||||||
|
|
||||||
|
let v_max_offset: usize = Self::max_offset(map_height, rows);
|
||||||
|
let h_max_offset: usize = Self::max_offset(map_width, cols);
|
||||||
|
|
||||||
|
let vertical_offset: Offset =
|
||||||
|
Offset::new(Some((map_height - rows as usize) / 2), Some(v_max_offset));
|
||||||
|
let horizontal_offset: Offset = Offset::new(None, Some(h_max_offset));
|
||||||
|
|
||||||
|
let focused_cell: FocusedCell =
|
||||||
|
FocusedCell::new((map_height / 2) - 1, 2, map_height, map_width);
|
||||||
|
|
||||||
|
let mut cells: Vec<CellWidget> = Vec::new();
|
||||||
|
|
||||||
|
for row in 0..map_height {
|
||||||
|
for col in 0..map_width {
|
||||||
|
cells.push(CellWidget::new(row, col, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
cells_area,
|
||||||
|
cell_width,
|
||||||
|
cell_height,
|
||||||
|
map_width,
|
||||||
|
map_height,
|
||||||
|
cols,
|
||||||
|
rows,
|
||||||
|
vertical_offset,
|
||||||
|
horizontal_offset,
|
||||||
|
cells,
|
||||||
|
zoom_level,
|
||||||
|
focused_cell,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zoom_change(&mut self, new_zoom_level: ZoomLevel) {
|
||||||
|
self.zoom_level = new_zoom_level;
|
||||||
|
|
||||||
|
self.cell_width = cell_size_helper(CellSizes::Width, self.zoom_level);
|
||||||
|
self.cell_height = cell_size_helper(CellSizes::Height, self.zoom_level);
|
||||||
|
|
||||||
|
self.cols = (self.cells_area.width / self.cell_width as u16) as usize;
|
||||||
|
self.rows = (self.cells_area.height / self.cell_height as u16) as usize;
|
||||||
|
|
||||||
|
let v_max_offset: usize = Self::max_offset(self.map_height, self.rows);
|
||||||
|
let h_max_offset: usize = Self::max_offset(self.map_width, self.cols);
|
||||||
|
|
||||||
|
self.vertical_offset =
|
||||||
|
Offset::new(Some(self.vertical_offset.get_value()), Some(v_max_offset));
|
||||||
|
self.horizontal_offset =
|
||||||
|
Offset::new(Some(self.horizontal_offset.get_value()), Some(h_max_offset));
|
||||||
|
|
||||||
|
self.focused_cell = FocusedCell::new(
|
||||||
|
self.focused_cell.row,
|
||||||
|
self.focused_cell.col,
|
||||||
|
self.map_height,
|
||||||
|
self.map_width,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_offset(map_size: usize, size: usize) -> usize {
|
||||||
|
if map_size > size { map_size - size } else { 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
|
pub mod board;
|
||||||
pub mod focused_cell;
|
pub mod focused_cell;
|
||||||
pub mod offset;
|
pub mod offset;
|
||||||
|
|
||||||
|
pub use board::BoardState;
|
||||||
pub use focused_cell::FocusedCell;
|
pub use focused_cell::FocusedCell;
|
||||||
pub use offset::Offset;
|
pub use offset::Offset;
|
||||||
|
|||||||
@@ -2,17 +2,13 @@
|
|||||||
pub struct Offset {
|
pub struct Offset {
|
||||||
value: usize,
|
value: usize,
|
||||||
max: usize,
|
max: usize,
|
||||||
value_initiated: bool,
|
|
||||||
max_initiated: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Offset {
|
impl Offset {
|
||||||
pub fn new() -> Self {
|
pub fn new(initial_value: Option<usize>, initial_max: Option<usize>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: 0,
|
value: initial_value.unwrap_or(0),
|
||||||
max: 0,
|
max: initial_max.unwrap_or(0),
|
||||||
value_initiated: false,
|
|
||||||
max_initiated: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,22 +16,12 @@ impl Offset {
|
|||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_initial_value(&mut self, value: usize) {
|
pub fn set_value(&mut self, value: usize) {
|
||||||
if self.value_initiated {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.value = value;
|
self.value = value;
|
||||||
self.value_initiated = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_max(&mut self, max: usize) {
|
pub fn set_max(&mut self, max: usize) {
|
||||||
if self.max_initiated {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.max = max;
|
self.max = max;
|
||||||
self.max_initiated = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(&mut self) {
|
pub fn next(&mut self) {
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ fn main_menu_layout(area: Rect) -> [Rect; 2] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_menu_view(app: &App, area: Rect, buf: &mut Buffer) {
|
pub fn main_menu_view(app: &App, area: Rect, buf: &mut Buffer) {
|
||||||
|
let Some(states) = app.states() else { return };
|
||||||
|
|
||||||
let [main_menu_area, keybindings_area] = main_menu_layout(area);
|
let [main_menu_area, keybindings_area] = main_menu_layout(area);
|
||||||
|
|
||||||
Block::new()
|
Block::new()
|
||||||
@@ -70,7 +72,7 @@ pub fn main_menu_view(app: &App, area: Rect, buf: &mut Buffer) {
|
|||||||
.map(|(i, view)| {
|
.map(|(i, view)| {
|
||||||
let view_string: String = main_menu_option_helper(format!("{:?}", view));
|
let view_string: String = main_menu_option_helper(format!("{:?}", view));
|
||||||
|
|
||||||
let styled: Line<'_> = if app.states.main_menu.selected_view == i {
|
let styled: Line<'_> = if states.main_menu.selected_view == i {
|
||||||
Line::from_iter(["> ".cyan(), view_string.yellow()]).yellow()
|
Line::from_iter(["> ".cyan(), view_string.yellow()]).yellow()
|
||||||
} else {
|
} else {
|
||||||
Line::from(format!(" {view_string}")).white()
|
Line::from(format!(" {view_string}")).white()
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ pub mod skirmish;
|
|||||||
|
|
||||||
pub use default::default_view;
|
pub use default::default_view;
|
||||||
pub use main_menu::main_menu_view;
|
pub use main_menu::main_menu_view;
|
||||||
pub use skirmish::skirmish_view;
|
pub use skirmish::{skirmish_layout, skirmish_view};
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const ACTIONS: &[Action] = &[
|
|||||||
Action::Esc,
|
Action::Esc,
|
||||||
];
|
];
|
||||||
|
|
||||||
fn skirmish_layout(area: Rect) -> [Rect; 3] {
|
pub fn skirmish_layout(area: Rect) -> [Rect; 3] {
|
||||||
Layout::vertical([
|
Layout::vertical([
|
||||||
Constraint::Length(4),
|
Constraint::Length(4),
|
||||||
Constraint::Fill(1),
|
Constraint::Fill(1),
|
||||||
@@ -37,22 +37,21 @@ fn skirmish_layout(area: Rect) -> [Rect; 3] {
|
|||||||
.areas(area)
|
.areas(area)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skirmish_view(app: &mut App, area: Rect, buf: &mut Buffer) {
|
pub fn skirmish_view(app: &App, area: Rect, buf: &mut Buffer) {
|
||||||
|
let Some(states) = app.states() else { return };
|
||||||
|
|
||||||
let [title_area, main_area, keybindings_area] = skirmish_layout(area);
|
let [title_area, main_area, keybindings_area] = skirmish_layout(area);
|
||||||
|
|
||||||
{
|
{
|
||||||
let lines: Vec<Line<'_>> = Vec::from_iter([
|
let lines: Vec<Line<'_>> = Vec::from_iter([
|
||||||
Line::raw("War in Tunnels").yellow(),
|
Line::raw("War in Tunnels").yellow(),
|
||||||
Line::from_iter([
|
Line::from_iter([
|
||||||
format!("Wood: {} (+{}) | ", app.states.settings.starting_wood, 5),
|
format!("Wood: {} (+{}) | ", states.settings.starting_wood, 5),
|
||||||
format!("Iron: {} (+{}) | ", app.states.settings.starting_iron, 1),
|
format!("Iron: {} (+{}) | ", states.settings.starting_iron, 1),
|
||||||
format!(
|
format!("Supply Limit: {}/{} | ", 10, states.settings.supply_limit),
|
||||||
"Supply Limit: {}/{} | ",
|
|
||||||
10, app.states.settings.supply_limit
|
|
||||||
),
|
|
||||||
format!(
|
format!(
|
||||||
"Skills points: {} ({}/{}) | ",
|
"Skills points: {} ({}/{}) | ",
|
||||||
1, 20, app.states.settings.skill_points_limit
|
1, 20, states.settings.skill_points_limit
|
||||||
),
|
),
|
||||||
format!("Perk Deck: {}/9", 5),
|
format!("Perk Deck: {}/9", 5),
|
||||||
]),
|
]),
|
||||||
@@ -91,7 +90,7 @@ pub fn skirmish_view(app: &mut App, area: Rect, buf: &mut Buffer) {
|
|||||||
vertical: 1,
|
vertical: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
BoardWidget::new(app, cells_area.width, cells_area.height).render(cells_area, buf);
|
BoardWidget::new(&states.skirmish.board).render(cells_area, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
+27
-71
@@ -1,9 +1,4 @@
|
|||||||
use crate::app::{
|
use crate::app::states::skirmish_states::BoardState;
|
||||||
App,
|
|
||||||
helpers::{CellSizes, cell_size_helper},
|
|
||||||
states::FocusedCell,
|
|
||||||
widgets::CellWidget,
|
|
||||||
};
|
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
layout::{Constraint, Layout, Rect},
|
layout::{Constraint, Layout, Rect},
|
||||||
@@ -12,87 +7,48 @@ use ratatui::{
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct BoardWidget<'a> {
|
pub struct BoardWidget<'a> {
|
||||||
map_width: usize,
|
state: &'a BoardState,
|
||||||
cell_width: u16,
|
|
||||||
cell_height: u16,
|
|
||||||
cols: u16,
|
|
||||||
rows: u16,
|
|
||||||
h_offset: usize,
|
|
||||||
v_offset: usize,
|
|
||||||
cells: &'a mut Vec<CellWidget>,
|
|
||||||
focused_cell: &'a FocusedCell,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BoardWidget<'a> {
|
impl<'a> BoardWidget<'a> {
|
||||||
fn max_offset(map_size: u16, size: u16) -> usize {
|
pub fn new(state: &'a BoardState) -> Self {
|
||||||
if map_size > size {
|
Self { state }
|
||||||
(map_size - size) as usize
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(app: &'a mut App, area_width: u16, area_height: u16) -> Self {
|
|
||||||
let cell_height: u16 = cell_size_helper(CellSizes::Height, app.states.skirmish.zoom_level);
|
|
||||||
let cell_width: u16 = cell_size_helper(CellSizes::Width, app.states.skirmish.zoom_level);
|
|
||||||
|
|
||||||
let rows: u16 = area_height / cell_height;
|
|
||||||
let cols: u16 = area_width / cell_width;
|
|
||||||
|
|
||||||
let v_max_offset: usize = Self::max_offset(app.states.skirmish.map_height as u16, rows);
|
|
||||||
let h_max_offset: usize = Self::max_offset(app.states.skirmish.map_width as u16, cols);
|
|
||||||
|
|
||||||
app.states.skirmish.horizontal_offset.set_max(h_max_offset);
|
|
||||||
app.states.skirmish.vertical_offset.set_max(v_max_offset);
|
|
||||||
|
|
||||||
if v_max_offset > 0 {
|
|
||||||
app.states
|
|
||||||
.skirmish
|
|
||||||
.vertical_offset
|
|
||||||
.set_initial_value((app.states.skirmish.map_height - rows as usize) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
|
||||||
map_width: app.states.skirmish.map_width as usize,
|
|
||||||
cell_width,
|
|
||||||
cell_height,
|
|
||||||
cols,
|
|
||||||
rows,
|
|
||||||
h_offset: app.states.skirmish.horizontal_offset.get_value(),
|
|
||||||
v_offset: app.states.skirmish.vertical_offset.get_value(),
|
|
||||||
cells: &mut app.states.skirmish.board_cells,
|
|
||||||
focused_cell: &app.states.skirmish.focused_cell,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for BoardWidget<'_> {
|
impl Widget for BoardWidget<'_> {
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
let horizontal: Rc<[Rect]> = Layout::horizontal(vec![
|
let horizontal: Rc<[Rect]> =
|
||||||
Constraint::Length(self.cell_width);
|
Layout::horizontal(vec![
|
||||||
self.cols as usize
|
Constraint::Length(self.state.cell_width as u16);
|
||||||
|
self.state.cols
|
||||||
])
|
])
|
||||||
.split(area);
|
.split(area);
|
||||||
|
|
||||||
for (col_idx, col_area) in horizontal.iter().enumerate() {
|
for (col_idx, col_area) in horizontal.iter().enumerate() {
|
||||||
let vertical: Rc<[Rect]> = Layout::vertical(vec![
|
let vertical: Rc<[Rect]> =
|
||||||
Constraint::Length(self.cell_height);
|
Layout::vertical(vec![
|
||||||
self.rows as usize
|
Constraint::Length(self.state.cell_height as u16);
|
||||||
|
self.state.rows
|
||||||
])
|
])
|
||||||
.split(*col_area);
|
.split(*col_area);
|
||||||
|
|
||||||
for (row_idx, cell_area) in vertical.iter().enumerate() {
|
for (row_idx, cell_area) in vertical.iter().enumerate() {
|
||||||
if let Some(cell) = self
|
if let Some(cell) = self.state.cells.get(
|
||||||
.cells
|
(row_idx + self.state.vertical_offset.get_value()) * self.state.map_width
|
||||||
.get_mut((row_idx + self.v_offset) * self.map_width + (col_idx + self.h_offset))
|
+ (col_idx + self.state.horizontal_offset.get_value()),
|
||||||
{
|
) {
|
||||||
if row_idx + self.v_offset == self.focused_cell.row
|
// FIXME: Fix showing selected cell
|
||||||
&& col_idx + self.h_offset == self.focused_cell.col
|
|
||||||
{
|
// if row_idx + self.state.vertical_offset.get_value()
|
||||||
cell.selected = true;
|
// == self.state.focused_cell.row
|
||||||
} else {
|
// && col_idx + self.state.horizontal_offset.get_value()
|
||||||
cell.selected = false;
|
// == self.state.focused_cell.col
|
||||||
}
|
// {
|
||||||
|
// cell.selected = true;
|
||||||
|
// } else {
|
||||||
|
// cell.selected = false;
|
||||||
|
// }
|
||||||
|
|
||||||
cell.render(*cell_area, buf);
|
cell.render(*cell_area, buf);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user