Flesh out bgmap viewer
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use egui::{Color32, Image, ImageSource, Response, Sense, TextureOptions, Ui, Widget};
|
||||
|
||||
pub const GENERIC_PALETTE: [u8; 4] = [0, 64, 128, 255];
|
||||
|
||||
pub fn parse_palette(palette: u8, brts: &[u8]) -> [u8; 4] {
|
||||
@@ -14,3 +16,100 @@ pub fn parse_palette(palette: u8, brts: &[u8]) -> [u8; 4] {
|
||||
shades[(palette >> 6) as usize & 0x03],
|
||||
]
|
||||
}
|
||||
|
||||
pub struct CharacterGrid<'a> {
|
||||
source: ImageSource<'a>,
|
||||
scale: f32,
|
||||
show_grid: bool,
|
||||
selected: Option<usize>,
|
||||
}
|
||||
|
||||
impl<'a> CharacterGrid<'a> {
|
||||
pub fn new(source: impl Into<ImageSource<'a>>) -> Self {
|
||||
Self {
|
||||
source: source.into(),
|
||||
scale: 1.0,
|
||||
show_grid: false,
|
||||
selected: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_scale(self, scale: f32) -> Self {
|
||||
Self { scale, ..self }
|
||||
}
|
||||
|
||||
pub fn with_grid(self, show_grid: bool) -> Self {
|
||||
Self { show_grid, ..self }
|
||||
}
|
||||
|
||||
pub fn with_selected(self, selected: usize) -> Self {
|
||||
Self {
|
||||
selected: Some(selected),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show(self, ui: &mut Ui) -> Option<usize> {
|
||||
let start_pos = ui.cursor().min;
|
||||
let cell_size = 8.0 * self.scale;
|
||||
|
||||
let res = self.ui(ui);
|
||||
|
||||
let grid_width_cells = ((res.rect.max.x - res.rect.min.x) / cell_size).round() as usize;
|
||||
|
||||
if res.clicked() {
|
||||
let click_pos = res.interact_pointer_pos()?;
|
||||
let grid_pos = (click_pos - start_pos) / cell_size;
|
||||
Some((grid_pos.y as usize * grid_width_cells) + grid_pos.x as usize)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for CharacterGrid<'_> {
|
||||
fn ui(self, ui: &mut Ui) -> Response {
|
||||
let image = Image::new(self.source)
|
||||
.fit_to_original_size(self.scale)
|
||||
.tint(Color32::RED)
|
||||
.texture_options(TextureOptions::NEAREST)
|
||||
.sense(Sense::click());
|
||||
let res = ui.add(image);
|
||||
|
||||
let cell_size = 8.0 * self.scale;
|
||||
let grid_width_cells = ((res.rect.max.x - res.rect.min.x) / cell_size).round() as usize;
|
||||
let grid_height_cells = ((res.rect.max.y - res.rect.min.y) / cell_size).round() as usize;
|
||||
|
||||
let painter = ui.painter_at(res.rect);
|
||||
if self.show_grid {
|
||||
let stroke = ui.style().visuals.widgets.noninteractive.fg_stroke;
|
||||
for x in (1..grid_width_cells).map(|i| (i as f32) * cell_size) {
|
||||
let p1 = (res.rect.min.x + x, res.rect.min.y).into();
|
||||
let p2 = (res.rect.min.x + x, res.rect.max.y).into();
|
||||
painter.line(vec![p1, p2], stroke);
|
||||
}
|
||||
for y in (1..grid_height_cells).map(|i| (i as f32) * cell_size) {
|
||||
let p1 = (res.rect.min.x, res.rect.min.y + y).into();
|
||||
let p2 = (res.rect.max.x, res.rect.min.y + y).into();
|
||||
painter.line(vec![p1, p2], stroke);
|
||||
}
|
||||
}
|
||||
if let Some(selected) = self.selected {
|
||||
let x1 = (selected % grid_width_cells) as f32 * cell_size;
|
||||
let x2 = x1 + cell_size;
|
||||
let y1 = (selected / grid_width_cells) as f32 * cell_size;
|
||||
let y2 = y1 + cell_size;
|
||||
painter.line(
|
||||
vec![
|
||||
(res.rect.min + (x1, y1).into()),
|
||||
(res.rect.min + (x2, y1).into()),
|
||||
(res.rect.min + (x2, y2).into()),
|
||||
(res.rect.min + (x1, y2).into()),
|
||||
(res.rect.min + (x1, y1).into()),
|
||||
],
|
||||
ui.style().visuals.widgets.active.fg_stroke,
|
||||
);
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user