Simplify main.rs: extract draw_board/pos_to_cell, deduplicate logic

- Extract draw_board() to eliminate duplicated board+player render loop in Edit and Play branches
- Extract pos_to_cell() to eliminate duplicated click-to-cell floor math in board and char grid handlers
- Simplify glyph dedup to use Glyph: PartialEq directly instead of manual key tuples
- Merge two identical clicked() handlers in archetype list into one || check
- Remove WHAT-explaining comments

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-17 18:35:21 -05:00
parent 5d97f67a64
commit 60b04e6ef3
+35 -62
View File
@@ -173,13 +173,9 @@ impl eframe::App for App {
p.text(r.center(), Align2::CENTER_CENTER,
glyph.ch, FontId::monospace(CELL_H), glyph.fg);
}
if cell_resp.clicked() {
self.editor.selected = archetype;
self.editor.glyph = archetype.default_glyph();
}
if ui.selectable_label(is_selected, archetype.name())
.clicked()
{
let label_resp =
ui.selectable_label(is_selected, archetype.name());
if cell_resp.clicked() || label_resp.clicked() {
self.editor.selected = archetype;
self.editor.glyph = archetype.default_glyph();
}
@@ -227,29 +223,10 @@ impl eframe::App for App {
// overflows the viewport, showing scroll bars as needed.
egui::ScrollArea::new([true, true]).show(ui, |ui| {
let (rect, response) = ui.allocate_exact_size(board_px, Sense::click());
{
let board = &self.state.board;
let painter = ui.painter();
for y in 0..board.height {
for x in 0..board.width {
let (glyph, _) = board.get(x, y);
draw_glyph(painter, rect.min, x, y, glyph);
}
}
let player_glyph = Glyph::player();
draw_glyph(
painter,
rect.min,
board.player.x as usize,
board.player.y as usize,
&player_glyph,
);
}
draw_board(ui.painter(), rect.min, &self.state.board);
if response.clicked() {
if let Some(pos) = response.interact_pointer_pos() {
let rel = pos - rect.min;
let cx = (rel.x / CELL_W).floor() as i32;
let cy = (rel.y / CELL_H).floor() as i32;
let (cx, cy) = pos_to_cell(rect.min, pos);
// floor() keeps out-of-bounds negatives negative; caught here.
if cx >= 0 && cy >= 0 {
let cx = cx as usize;
@@ -268,27 +245,7 @@ impl eframe::App for App {
let available = ui.available_rect_before_wrap();
let player = self.state.board.player;
let origin = board_origin(available, board_w, board_h, player);
{
let board = &self.state.board;
let painter = ui.painter();
for y in 0..board.height {
for x in 0..board.width {
let (glyph, _) = board.get(x, y);
draw_glyph(painter, origin, x, y, glyph);
}
}
// Draw the player on top of the board. The player is not stored as
// a board cell, so it is rendered as a separate overlay. This will
// change once the player becomes a scripted object.
let player_glyph = Glyph::player();
draw_glyph(
painter,
origin,
board.player.x as usize,
board.player.y as usize,
&player_glyph,
);
}
draw_board(ui.painter(), origin, &self.state.board);
}
});
@@ -298,16 +255,13 @@ impl eframe::App for App {
// Collect unique glyphs from the board before the window closure
// borrows self mutably, to avoid a conflict with self.state.board.
let board_glyphs: Vec<Glyph> = {
let mut seen: Vec<(u32, [u8; 4], [u8; 4])> = Vec::new();
let mut out: Vec<Glyph> = Vec::new();
let mut seen: Vec<Glyph> = Vec::new();
for (glyph, _) in &self.state.board.cells {
let key = (glyph.ch as u32, glyph.fg.to_array(), glyph.bg.to_array());
if !seen.contains(&key) {
seen.push(key);
out.push(*glyph);
if !seen.contains(glyph) {
seen.push(*glyph);
}
}
out
seen
};
// Use a local bool so the window's close button can write to it
@@ -365,7 +319,6 @@ impl eframe::App for App {
let grid_size = vec2(CHAR_COLS as f32 * CELL_W, rows as f32 * CELL_H);
let (grid_rect, grid_resp) =
ui.allocate_exact_size(grid_size, Sense::click());
// Copy colors and selected char before painter borrow.
let fg = self.editor.glyph.fg;
let bg = self.editor.glyph.bg;
let cur_ch = self.editor.glyph.ch;
@@ -388,17 +341,14 @@ impl eframe::App for App {
}
if grid_resp.clicked() {
if let Some(pos) = grid_resp.interact_pointer_pos() {
let rel = pos - grid_rect.min;
let col = (rel.x / CELL_W).floor() as usize;
let row = (rel.y / CELL_H).floor() as usize;
let idx = row * CHAR_COLS + col;
let (col, row) = pos_to_cell(grid_rect.min, pos);
let idx = row as usize * CHAR_COLS + col as usize;
if let Some(&ch) = chars.get(idx) {
self.editor.glyph.ch = ch;
}
}
}
});
// Window's close button sets picker_open to false.
self.editor.glyph_picker_open = picker_open;
}
@@ -425,6 +375,29 @@ fn draw_glyph(painter: &egui::Painter, origin: Pos2, x: usize, y: usize, glyph:
painter.text(center, Align2::CENTER_CENTER, glyph.ch, FontId::monospace(CELL_H), glyph.fg);
}
/// Draws all board cells then the player overlay at `origin`.
fn draw_board(painter: &egui::Painter, origin: Pos2, board: &game::Board) {
for y in 0..board.height {
for x in 0..board.width {
let (glyph, _) = board.get(x, y);
draw_glyph(painter, origin, x, y, glyph);
}
}
// The player is not a board cell; it is rendered on top as an overlay.
// This separate draw will be removed once the player becomes a scripted object.
let player_glyph = Glyph::player();
draw_glyph(painter, origin, board.player.x as usize, board.player.y as usize, &player_glyph);
}
/// Converts a pixel position to cell coordinates relative to `origin`.
///
/// Uses floor so positions above or left of `origin` produce negative values —
/// callers must guard `>= 0` before treating the result as a valid cell index.
fn pos_to_cell(origin: Pos2, pos: Pos2) -> (i32, i32) {
let rel = pos - origin;
((rel.x / CELL_W).floor() as i32, (rel.y / CELL_H).floor() as i32)
}
/// Computes the pixel position of board cell (0, 0) within `available`.
///
/// If the board fits along an axis, it is centered. If it overflows, the