From ae477ea5664b32eb6149a3bd7cb59c5b841eda69 Mon Sep 17 00:00:00 2001 From: Aaron Seilis Date: Sat, 4 Jan 2025 11:23:30 -0800 Subject: [PATCH] Add simple editing to rpgmap-gui Add a side panel that allows the user to set the cursor to modify the type of cells that are clicked on (e.g. from a room to nothing). --- src/bin/rpgmap-gui.rs | 75 ++++++++++++++++++++++++---- src/rpgtools/map/gridmap.rs | 5 ++ src/rpgtools/map/gridmap/gridcell.rs | 5 ++ 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/src/bin/rpgmap-gui.rs b/src/bin/rpgmap-gui.rs index 0513058..b51d9bf 100644 --- a/src/bin/rpgmap-gui.rs +++ b/src/bin/rpgmap-gui.rs @@ -81,13 +81,6 @@ fn main() { let height: usize = *cli .get_one::("height") .expect("failed to get height; this is a bug") as usize; - let scale: usize = *cli - .get_one::("scale") - .expect("failed to get scale; this is a bug") as usize; - let filename: String = cli - .get_one::("output") - .expect("failed to get filename; this is a bug") - .to_string(); let num_rooms: usize = *cli .get_one::("num_rooms") .expect("failed to get num_rooms; this is a bug") as usize; @@ -118,13 +111,33 @@ fn main() { ); } +enum Tool { + CellPainter(AreaType), + // Move + // CellSelection + // ??? +} + +impl Default for Tool { + fn default() -> Self { + Self::CellPainter(AreaType::Room) + } +} + struct RpgMapGui { + // Map state map: GridMap, + // Current Tool selection + tool: Tool, + // Mouse state + dragging: bool, } impl RpgMapGui { fn new(map: GridMap) -> Self { - Self { map } + let tool = Tool::default(); + let dragging = false; + Self { map, tool, dragging } } } @@ -153,6 +166,25 @@ impl eframe::App for RpgMapGui { }); }); + egui::SidePanel::left("edit_widgets").show(ctx, |ui| { + ui.label("Edit"); + + if ui.button("Room").clicked() { + // Set the tool type to room + self.tool = Tool::CellPainter(AreaType::Room); + } + + if ui.button("Nothing").clicked() { + // Set the tool type to nothing + self.tool = Tool::CellPainter(AreaType::Nothing); + } + + if ui.button("Entrance").clicked() { + // Set the tool type to Entrance + self.tool = Tool::CellPainter(AreaType::Entrance); + } + }); + egui::CentralPanel::default().show(ctx, |ui| { let cell_size = 20.0; @@ -161,6 +193,16 @@ impl eframe::App for RpgMapGui { egui::ScrollArea::both().show(ui, |ui| { let scroll_offset = ui.cursor().left_top(); + // Figure out if we're clicking in this region + ctx.input(|input| { + if input.pointer.primary_down() { + self.dragging = true; + } + if input.pointer.primary_released() { + self.dragging = false; + } + }); + for x in 0..num_x { for y in 0..num_y { let cell_x = scroll_offset.x + x as f32 * cell_size; @@ -174,9 +216,8 @@ impl eframe::App for RpgMapGui { egui::Sense::drag(), // "click_and_drag" has latency ); - let map_cell = self.map.get_cell_ref(x, y); - - let color = match map_cell.area() { + // TODO: Refactor this into an into() call. + let color = match self.map.get_cell_ref(x,y).area() { AreaType::Room => egui::Color32::LIGHT_GRAY, AreaType::Entrance => egui::Color32::RED, AreaType::Nothing => egui::Color32::DARK_GRAY, @@ -190,6 +231,18 @@ impl eframe::App for RpgMapGui { 0.0, egui::Stroke::new(1.0, egui::Color32::BLACK), ); + + // If the mouse main button is down then we may need to + // set a cell. + if self.dragging && cell.rect.contains(ctx.pointer_hover_pos().unwrap_or_default()) { + if let Tool::CellPainter(ref area) = &self.tool { + self.map.get_cell_mut(x, y).set_area(area.to_owned()); + } + } else if ui.interact(cell.rect, egui::Id::new((x, y)), egui::Sense::click()).clicked() { + if let Tool::CellPainter(ref area) = &self.tool { + self.map.get_cell_mut(x, y).set_area(area.to_owned()); + } + } } } }); diff --git a/src/rpgtools/map/gridmap.rs b/src/rpgtools/map/gridmap.rs index 1dd3684..d223378 100644 --- a/src/rpgtools/map/gridmap.rs +++ b/src/rpgtools/map/gridmap.rs @@ -67,6 +67,11 @@ impl GridMap { &self.cells[x][y] } + /// Get a mutable reference to a GridCell at coordinate. + pub fn get_cell_mut(&mut self, x: usize, y: usize) -> &mut GridCell { + &mut self.cells[x][y] + } + /// Set the entrance at a particular location. The cell at this location /// will be marked as having the entrance area type. Typically this will /// be coloured differently on a map. diff --git a/src/rpgtools/map/gridmap/gridcell.rs b/src/rpgtools/map/gridmap/gridcell.rs index 0c01867..164e40c 100644 --- a/src/rpgtools/map/gridmap/gridcell.rs +++ b/src/rpgtools/map/gridmap/gridcell.rs @@ -80,6 +80,11 @@ impl GridCell { pub fn area(&self) -> &AreaType { &self.area } + + /// Set the type of area that this cell represents + pub fn set_area(&mut self, area: AreaType) { + self.area = area; + } } impl Default for GridCell {