diff --git a/src/editor.rs b/src/editor.rs index fcea22e..3ad00da 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -181,11 +181,16 @@ impl Editor { fn do_action(&mut self, action: Action) { match action { - Action::SetTile(resize_delta, pos, _old, new) => { - self.resize_board(resize_delta); + Action::SetTile(deltas, pos, _old, new) => { + self.shift_view(deltas.x_neg as f32, deltas.y_neg as f32); + self.source_board.grow(&deltas); self.source_board.set(pos, new); } - Action::SetArea(_, _, _, _) => todo!(), + Action::SetArea(deltas, pos, _old, new) => { + self.shift_view(deltas.x_neg as f32, deltas.y_neg as f32); + self.source_board.grow(&deltas); + self.source_board.paste_board(pos, &new); + } } } @@ -196,26 +201,39 @@ impl Editor { self.undo_index -= 1; let action = self.undo_history[self.undo_index].clone(); match action { - Action::SetTile(resize_delta, pos, old, _new) => { + Action::SetTile(deltas, pos, old, _new) => { self.source_board.set(pos, old); - self.undo_resize_board(resize_delta); + self.source_board.shrink(&deltas); + self.shift_view(-(deltas.x_neg as f32), -(deltas.y_neg as f32)); + } + Action::SetArea(deltas, pos, old, _new) => { + self.source_board.paste_board(pos, &old); + self.source_board.shrink(&deltas); + self.shift_view(-(deltas.x_neg as f32), -(deltas.y_neg as f32)); } - Action::SetArea(_, _, _, _) => todo!(), } } - fn resize_board(&mut self, deltas: ResizeDeltas) { - self.source_board.grow(&deltas); + fn shift_view(&mut self, x: f32, y: f32) { + match &mut self.active_tool { + Tool::SelectArea(Selection { + area: Some((a, b)), + is_selecting: _, + }) => { + a.x += x as PosInt; + a.y += y as PosInt; + b.x += x as PosInt; + b.y += y as PosInt; + } + Tool::Digits(Some(pos)) => { + pos.x += x as PosInt; + pos.y += y as PosInt; + } + _ => (), + } let tile_size = TILE_TEXTURE_SIZE * self.zoom; - self.view_offset.x -= deltas.x_neg as f32 * tile_size; - self.view_offset.y -= deltas.y_neg as f32 * tile_size; - } - - fn undo_resize_board(&mut self, deltas: ResizeDeltas) { - self.source_board.shrink(&deltas); - let tile_size = TILE_TEXTURE_SIZE * self.zoom; - self.view_offset.x += deltas.x_neg as f32 * tile_size; - self.view_offset.y += deltas.y_neg as f32 * tile_size; + self.view_offset.x -= x * tile_size; + self.view_offset.y -= y * tile_size; } pub fn get_exit_state(&self) -> ExitState { @@ -356,31 +374,39 @@ impl Editor { self.active_tool = Tool::Blueprint; } - fn grow_board_and_update_view(&mut self, pos: &mut Pos) { - let tile_size = TILE_TEXTURE_SIZE * self.zoom; - let (x, y) = self.source_board.grow_to_include(*pos); - if x != 0 || y != 0 { - self.view_offset.x -= x as f32 * tile_size; - self.view_offset.y -= y as f32 * tile_size; - pos.x += x; - pos.y += y; - match &mut self.active_tool { - Tool::Digits(Some(pos)) => { - pos.x += x; - pos.y += y; - } - Tool::SelectArea(Selection { - area: Some((start, end)), - is_selecting: _, - }) => { - start.x += x; - start.y += y; - end.x += x; - end.y += y; - } - _ => (), - } + fn set_area(&mut self, pos: Pos, area: Board) { + let old_area = self.source_board.get_rect(pos, area.width(), area.height()); + if area == old_area { + return; } + let width = self.source_board.width() as PosInt; + let height = self.source_board.height() as PosInt; + let resize = ResizeDeltas { + x_pos: if (pos.x + BOARD_MARGIN + area.width() as PosInt) > width { + pos.x + BOARD_MARGIN + area.width() as PosInt - width + } else { + 0 + } as usize, + x_neg: if pos.x < BOARD_MARGIN { + BOARD_MARGIN - pos.x + } else { + 0 + } as usize, + y_pos: if (pos.y + BOARD_MARGIN + area.height() as PosInt) > height { + pos.y + BOARD_MARGIN + area.height() as PosInt - height + } else { + 0 + } as usize, + y_neg: if pos.y < BOARD_MARGIN { + BOARD_MARGIN - pos.y + } else { + 0 + } as usize, + }; + let mut pos = pos; + pos.x += resize.x_neg as PosInt; + pos.y += resize.y_neg as PosInt; + self.push_action(Action::SetArea(resize, pos, old_area, area)); } fn set_tile(&mut self, pos: Pos, tile: Tile) { @@ -825,11 +851,9 @@ impl Editor { if simple_button(d, 232, y, 40, 40) { let min = selection.0.min(selection.1); let max = selection.0.max(selection.1); - for x in min.x..=max.x { - for y in min.y..=max.y { - self.source_board.set(Pos { x, y }, Tile::BLANK); - } - } + let board = + Board::new_empty((max.x - min.x) as usize + 1, (max.y - min.y) as usize + 1); + self.set_area(min, board); } draw_scaled_texture(d, textures.get("eraser"), 236, y + 4, 2.); } @@ -1003,14 +1027,8 @@ impl Editor { if d.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT) { let tile_pos = (mouse_pos - self.view_offset) / tile_size; let tile_pos = Vector2::new(tile_pos.x.floor(), tile_pos.y.floor()); - let mut pos = tile_pos.into(); - let board = self.pasting_board.take().unwrap(); - self.grow_board_and_update_view(&mut pos); - self.grow_board_and_update_view( - &mut (pos + (board.width() - 1, board.height() - 1).into()), - ); - self.source_board.paste_board(pos, &board); + self.set_area(tile_pos.into(), board); } } return; @@ -1106,12 +1124,7 @@ impl Editor { if mouse_pos.x > SIDEBAR_WIDTH as f32 { if let Some(bp) = self.blueprints.get(self.selected_blueprint) { let board = bp.get_board().unwrap().clone(); - let mut pos = pos; - self.grow_board_and_update_view(&mut pos); - self.grow_board_and_update_view( - &mut (pos + (board.width() - 1, board.height() - 1).into()), - ); - self.source_board.paste_board(pos, &board); + self.set_area(pos, board); } } } diff --git a/src/marble_engine/board.rs b/src/marble_engine/board.rs index 2f10308..b7539de 100644 --- a/src/marble_engine/board.rs +++ b/src/marble_engine/board.rs @@ -6,7 +6,7 @@ use super::Pos; use super::PosInt; use raylib::prelude::*; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct Board { rows: Vec>, width: usize, @@ -140,41 +140,6 @@ impl Board { out } - pub fn grow_to_include(&mut self, p: Pos) -> (PosInt, PosInt) { - let mut offset_x = 0; - let mut offset_y = 0; - if p.x < 0 { - let len = p.x.unsigned_abs() as usize; - for row in &mut self.rows { - let mut new_row = vec![Tile::BLANK; len]; - new_row.append(row); - *row = new_row; - } - offset_x = len; - self.width += len; - } else if p.x as usize >= self.width { - let new_width = p.x as usize + 1; - for row in &mut self.rows { - row.resize(new_width, Tile::BLANK); - } - self.width = new_width; - } - - if p.y < 0 { - let len = p.y.unsigned_abs() as usize; - let mut new_rows = vec![vec![Tile::BLANK; self.width]; len]; - new_rows.append(&mut self.rows); - self.rows = new_rows; - offset_y = len; - self.height += len; - } else if p.y as usize >= self.height { - let new_height = p.y as usize + 1; - self.rows.resize(new_height, vec![Tile::BLANK; self.width]); - self.height = new_height; - } - (offset_x as PosInt, offset_y as PosInt) - } - pub fn trim_size(&mut self, margin: usize) -> (usize, usize) { let (offset_x, offset_y); // top @@ -235,7 +200,6 @@ impl Board { } pub fn grow(&mut self, deltas: &ResizeDeltas) { - // dbg!(&deltas); 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); @@ -249,7 +213,6 @@ impl Board { } pub fn shrink(&mut self, deltas: &ResizeDeltas) { - // dbg!(&deltas); 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);