diff --git a/src/editor.rs b/src/editor.rs index c359b23..467a445 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -350,8 +350,7 @@ impl Editor { } fn save_blueprint(&mut self, selection: (Pos, Pos)) { - let mut board = self.get_selected_as_board(selection); - board.trim_size(0); + let board = self.get_selected_as_board(selection); let id = get_free_id(&self.blueprints, Blueprint::id); let mut blueprint = Blueprint::new(&board, id); if !self.new_blueprint_name.is_empty() { @@ -1086,7 +1085,6 @@ impl Editor { Tool::Mirror => self.set_tile(pos, Tile::Mirror(self.tool_mirror)), Tool::Digits(_pos) => { self.active_tool = Tool::Digits(Some(pos)); - let tile = self.source_board.get_or_blank(pos); if !matches!(tile, Tile::Open(OpenTile::Digit(_), _)) { self.set_tile(pos, Tile::Open(OpenTile::Digit(0), Claim::Free)); diff --git a/src/marble_engine/board.rs b/src/marble_engine/board.rs index 0dd1954..10b56fe 100644 --- a/src/marble_engine/board.rs +++ b/src/marble_engine/board.rs @@ -8,7 +8,7 @@ use raylib::prelude::*; #[derive(Debug, Clone, PartialEq)] pub struct Board { - rows: Vec>, + tiles: Vec, width: usize, height: usize, } @@ -26,7 +26,9 @@ impl Board { let mut rows = Vec::new(); let mut width = 0; + let mut height = 0; for line in source.lines() { + height += 1; width = width.max(line.len()); let mut tiles = Vec::new(); for char in line.chars() { @@ -37,14 +39,20 @@ impl Board { for line in &mut rows { line.resize(width, Tile::BLANK); } + let tiles = rows.into_iter().flatten().collect(); - Board::new(rows) + Self { + tiles, + width, + height, + } } pub fn to_string(&self) -> String { let mut out = String::new(); - for row in &self.rows { - for tile in row { + for y in 0..self.height { + for x in 0..self.width { + let tile = self.get((x, y).into()).unwrap(); out.push(tile.to_char()); } out.push('\n'); @@ -53,9 +61,9 @@ impl Board { } pub fn new_empty(width: usize, height: usize) -> Self { - let rows = vec![vec![Tile::BLANK; width]; height]; + let tiles = vec![Tile::BLANK; width * height]; Self { - rows, + tiles, width, height, } @@ -63,28 +71,17 @@ impl Board { pub fn new_single(tile: Tile) -> Self { Self { - rows: vec![vec![tile]], + tiles: vec![tile], width: 1, height: 1, } } - pub fn new(rows: Vec>) -> Self { - Self { - width: rows[0].len(), - height: rows.len(), - rows, - } - } - pub fn count_tiles(&self) -> usize { let mut sum = 0; - for row in &self.rows { - for tile in row { - match tile { - Tile::Open(OpenTile::Blank, _) | Tile::Block => (), - _ => sum += 1, - } + for tile in &self.tiles { + if !matches!(tile, Tile::Open(OpenTile::Blank, _) | Tile::Block) { + sum += 1 } } sum @@ -94,9 +91,13 @@ impl Board { p.x >= 0 && p.y >= 0 && p.x < self.width as PosInt && p.y < self.height as PosInt } + fn get_unchecked(&self, p: Pos) -> Tile { + self.tiles[p.y as usize * self.width + p.x as usize] + } + pub fn get(&self, p: Pos) -> Option { if self.in_bounds(p) { - Some(self.rows[p.y as usize][p.x as usize]) + Some(self.get_unchecked(p)) } else { None } @@ -104,7 +105,7 @@ impl Board { pub fn get_or_blank(&self, p: Pos) -> Tile { if self.in_bounds(p) { - self.rows[p.y as usize][p.x as usize] + self.get_unchecked(p) } else { Tile::BLANK } @@ -112,7 +113,7 @@ impl Board { pub fn get_mut(&mut self, p: Pos) -> Option<&mut Tile> { if self.in_bounds(p) { - Some(&mut self.rows[p.y as usize][p.x as usize]) + Some(&mut self.tiles[p.y as usize * self.width + p.x as usize]) } else { None } @@ -120,7 +121,7 @@ impl Board { pub fn set(&mut self, p: Pos, tile: Tile) { if self.in_bounds(p) { - self.rows[p.y as usize][p.x as usize] = tile; + self.tiles[p.y as usize * self.width + p.x as usize] = tile; } } @@ -148,73 +149,14 @@ impl Board { out } - pub fn trim_size(&mut self, margin: usize) -> (usize, usize) { - let (offset_x, offset_y); - // top - { - let mut n = 0; - while n < self.height && self.rows[n].iter().all(|t| t.is_blank()) { - n += 1; - } - let trim_top = n.saturating_sub(margin); - for _ in 0..trim_top { - self.rows.remove(0); - } - offset_y = trim_top; - self.height -= trim_top; - } - // bottom - { - let mut n = 0; - while n < self.height && self.rows[self.height - n - 1].iter().all(|t| t.is_blank()) { - n += 1; - } - let trim_bottom = n.saturating_sub(margin); - for _ in 0..trim_bottom { - self.rows.pop(); - } - self.height -= trim_bottom; - } - // left - { - let mut n = 0; - while n < self.width && self.rows.iter().all(|row| row[n].is_blank()) { - n += 1; - } - let trim_left = n.saturating_sub(margin); - for row in &mut self.rows { - for _ in 0..trim_left { - row.remove(0); - } - } - offset_x = trim_left; - self.width -= trim_left; - } - // right - { - let mut n = 0; - while n < self.width && self.rows.iter().all(|r| r[self.width - n - 1].is_blank()) { - n += 1; - } - let trim_right = n.saturating_sub(margin); - for row in &mut self.rows { - for _ in 0..trim_right { - row.pop(); - } - } - self.width -= trim_right; - } - (offset_x, offset_y) - } - pub fn grow(&mut self, deltas: &ResizeDeltas) { let new_width = self.width + deltas.x_neg + deltas.x_pos; let new_height = self.height + deltas.y_neg + deltas.y_pos; let mut new_board = Board::new_empty(new_width, new_height); for x in 0..self.width { for y in 0..self.height { - let tile = self.rows[y][x]; - new_board.rows[y + deltas.y_neg][x + deltas.x_neg] = tile; + let tile = self.get_unchecked((x, y).into()); + new_board.set((x + deltas.x_neg, y + deltas.y_neg).into(), tile); } } *self = new_board; @@ -226,8 +168,8 @@ impl Board { let mut new_board = Board::new_empty(new_width, new_height); for x in 0..new_width { for y in 0..new_height { - let tile = self.rows[y + deltas.y_neg][x + deltas.x_neg]; - new_board.rows[y][x] = tile; + let tile = self.get_unchecked((x + deltas.x_neg, y + deltas.y_neg).into()); + new_board.set((x, y).into(), tile); } } *self = new_board; @@ -245,7 +187,7 @@ impl Board { let mut out = Vec::new(); for y in 0..self.height { for x in 0..self.width { - if let Tile::Marble { value: _, dir: _ } = self.rows[y][x] { + if let Tile::Marble { value: _, dir: _ } = self.get_unchecked((x, y).into()) { out.push((x, y).into()); } }