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:
@@ -1,34 +1,11 @@
|
||||
use crate::app::{
|
||||
states::{FocusedCell, Offset},
|
||||
widgets::CellWidget,
|
||||
};
|
||||
use crate::app::states::skirmish_states::BoardState;
|
||||
use clap::ValueEnum;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct SkirmishState {
|
||||
pub id: usize,
|
||||
pub name: &'static str,
|
||||
pub map_width: usize,
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
pub board: BoardState,
|
||||
}
|
||||
|
||||
#[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 offset;
|
||||
|
||||
pub use board::BoardState;
|
||||
pub use focused_cell::FocusedCell;
|
||||
pub use offset::Offset;
|
||||
|
||||
@@ -2,17 +2,13 @@
|
||||
pub struct Offset {
|
||||
value: usize,
|
||||
max: usize,
|
||||
value_initiated: bool,
|
||||
max_initiated: bool,
|
||||
}
|
||||
|
||||
impl Offset {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(initial_value: Option<usize>, initial_max: Option<usize>) -> Self {
|
||||
Self {
|
||||
value: 0,
|
||||
max: 0,
|
||||
value_initiated: false,
|
||||
max_initiated: false,
|
||||
value: initial_value.unwrap_or(0),
|
||||
max: initial_max.unwrap_or(0),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,22 +16,12 @@ impl Offset {
|
||||
self.value
|
||||
}
|
||||
|
||||
pub fn set_initial_value(&mut self, value: usize) {
|
||||
if self.value_initiated {
|
||||
return;
|
||||
}
|
||||
|
||||
pub fn set_value(&mut self, value: usize) {
|
||||
self.value = value;
|
||||
self.value_initiated = true;
|
||||
}
|
||||
|
||||
pub fn set_max(&mut self, max: usize) {
|
||||
if self.max_initiated {
|
||||
return;
|
||||
}
|
||||
|
||||
self.max = max;
|
||||
self.max_initiated = true;
|
||||
}
|
||||
|
||||
pub fn next(&mut self) {
|
||||
|
||||
Reference in New Issue
Block a user