112 lines
4.3 KiB
Rust
112 lines
4.3 KiB
Rust
|
|
use eframe::egui;
|
|||
|
|
use egui::{Align2, Color32, FontId, Rect, Sense, Stroke, vec2};
|
|||
|
|
|
|||
|
|
use crate::game::{Archetype, Glyph};
|
|||
|
|
use crate::render::{CELL_H, CELL_W, pos_to_cell};
|
|||
|
|
|
|||
|
|
/// Renders the floating glyph-picker dialog and updates `glyph` in place.
|
|||
|
|
///
|
|||
|
|
/// Shows three sections: board palette (unique glyphs on the current board),
|
|||
|
|
/// FG/BG color pickers, and a 16×6 printable-ASCII character grid.
|
|||
|
|
/// Closes when the window's X button is clicked, writing `false` to `open`.
|
|||
|
|
pub(crate) fn show(
|
|||
|
|
ctx: &egui::Context,
|
|||
|
|
open: &mut bool,
|
|||
|
|
glyph: &mut Glyph,
|
|||
|
|
board_cells: &[(Glyph, Archetype)],
|
|||
|
|
) {
|
|||
|
|
// Collect unique glyphs from the board before the window closure borrows
|
|||
|
|
// `glyph` mutably, to avoid a borrow conflict with `board_cells`.
|
|||
|
|
let board_glyphs: Vec<Glyph> = {
|
|||
|
|
let mut seen: Vec<Glyph> = Vec::new();
|
|||
|
|
for (g, _) in board_cells {
|
|||
|
|
if !seen.contains(g) {
|
|||
|
|
seen.push(*g);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
seen
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
egui::Window::new("Glyph")
|
|||
|
|
.collapsible(false)
|
|||
|
|
.resizable(false)
|
|||
|
|
.open(open)
|
|||
|
|
.show(ctx, |ui| {
|
|||
|
|
// ----- Board palette -----
|
|||
|
|
ui.label("Board palette");
|
|||
|
|
ui.horizontal_wrapped(|ui| {
|
|||
|
|
for &g in &board_glyphs {
|
|||
|
|
let (r, resp) =
|
|||
|
|
ui.allocate_exact_size(vec2(CELL_W, CELL_H), Sense::click());
|
|||
|
|
{
|
|||
|
|
let p = ui.painter();
|
|||
|
|
p.rect_filled(r, 0.0, g.bg);
|
|||
|
|
p.text(r.center(), Align2::CENTER_CENTER, g.ch,
|
|||
|
|
FontId::monospace(CELL_H), g.fg);
|
|||
|
|
if g == *glyph {
|
|||
|
|
p.rect_stroke(r, 0.0, Stroke::new(1.0, Color32::WHITE),
|
|||
|
|
egui::epaint::StrokeKind::Middle);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if resp.clicked() {
|
|||
|
|
*glyph = g;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
ui.separator();
|
|||
|
|
|
|||
|
|
// ----- Colors -----
|
|||
|
|
ui.label("Colors");
|
|||
|
|
ui.horizontal(|ui| {
|
|||
|
|
ui.label("FG");
|
|||
|
|
egui::color_picker::color_edit_button_srgba(
|
|||
|
|
ui, &mut glyph.fg, egui::color_picker::Alpha::Opaque);
|
|||
|
|
ui.label("BG");
|
|||
|
|
egui::color_picker::color_edit_button_srgba(
|
|||
|
|
ui, &mut glyph.bg, egui::color_picker::Alpha::Opaque);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
ui.separator();
|
|||
|
|
|
|||
|
|
// ----- Character grid -----
|
|||
|
|
// 16 columns × 6 rows covering printable ASCII 0x20–0x7E.
|
|||
|
|
ui.label("Character");
|
|||
|
|
const CHAR_COLS: usize = 16;
|
|||
|
|
let chars: Vec<char> =
|
|||
|
|
(0x20u32..=0x7eu32).filter_map(char::from_u32).collect();
|
|||
|
|
let rows = chars.len().div_ceil(CHAR_COLS);
|
|||
|
|
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());
|
|||
|
|
let fg = glyph.fg;
|
|||
|
|
let bg = glyph.bg;
|
|||
|
|
let cur_ch = glyph.ch;
|
|||
|
|
{
|
|||
|
|
let p = ui.painter();
|
|||
|
|
for (i, &ch) in chars.iter().enumerate() {
|
|||
|
|
let col = i % CHAR_COLS;
|
|||
|
|
let row = i / CHAR_COLS;
|
|||
|
|
let tl = grid_rect.min
|
|||
|
|
+ vec2(col as f32 * CELL_W, row as f32 * CELL_H);
|
|||
|
|
let cell = Rect::from_min_size(tl, vec2(CELL_W, CELL_H));
|
|||
|
|
p.rect_filled(cell, 0.0, bg);
|
|||
|
|
p.text(cell.center(), Align2::CENTER_CENTER, ch,
|
|||
|
|
FontId::monospace(CELL_H), fg);
|
|||
|
|
if ch == cur_ch {
|
|||
|
|
p.rect_stroke(cell, 0.0, Stroke::new(1.0, Color32::WHITE),
|
|||
|
|
egui::epaint::StrokeKind::Middle);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if grid_resp.clicked()
|
|||
|
|
&& let Some(pos) = grid_resp.interact_pointer_pos() {
|
|||
|
|
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) {
|
|||
|
|
glyph.ch = ch;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|