From c71cc73406d823edaa324fb85caf1b4a1397b66c Mon Sep 17 00:00:00 2001 From: grimsace Date: Mon, 18 May 2026 10:30:59 -0500 Subject: [PATCH] massive commenting pass to explain random functions and their purpose --- src/app.rs | 22 +++++++++++++++++ src/exporter/mod.rs | 14 +++++++++++ src/exporter/raster.rs | 25 +++++++++++++++++++ src/exporter/svg.rs | 4 ++++ src/exporter/types.rs | 9 +++++++ src/exporter/utils.rs | 5 ++++ src/interact/add_delete.rs | 10 ++++++++ src/interact/drag.rs | 7 ++++++ src/interact/mod.rs | 32 +++++++++++++++++++++++++ src/interact/resize.rs | 7 ++++++ src/layout/generation/connections.rs | 6 +++++ src/layout/generation/markers.rs | 24 +++++++++++++++++++ src/layout/generation/mod.rs | 1 + src/layout/generation/passages.rs | 15 ++++++++++++ src/layout/generation/room_placement.rs | 7 ++++++ src/layout/utils.rs | 6 +++++ src/rendering.rs | 16 +++++++++++++ src/saveandload.rs | 2 ++ src/ui/mod.rs | 12 ++++++++++ src/ui/tabs.rs | 3 +++ src/ui/widgets.rs | 2 ++ 21 files changed, 229 insertions(+) diff --git a/src/app.rs b/src/app.rs index a19ca4f..167cb53 100644 --- a/src/app.rs +++ b/src/app.rs @@ -56,6 +56,7 @@ pub struct DungeonApp { } impl Default for DungeonApp { + // Provides default settings for this type. fn default() -> Self { let settings = settings::load_settings().unwrap_or_default(); let mut app = Self { @@ -89,6 +90,7 @@ impl Default for DungeonApp { } impl Drop for DungeonApp { + // Cleans up background resources when the app is dropped. fn drop(&mut self) { if let Err(err) = settings::save_settings(&self.settings) { eprintln!("Failed to save settings: {err}"); @@ -97,6 +99,7 @@ impl Drop for DungeonApp { } impl eframe::App for DungeonApp { + // Runs one UI frame and handles app interaction. fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { let panel_result = draw_side_panel( ctx, @@ -299,6 +302,7 @@ impl eframe::App for DungeonApp { } } +// Generates all levels. pub fn generate_all_levels(settings: &UiSettings) -> Vec { let level_count = if settings.min_levels == settings.max_levels { settings.min_levels @@ -315,6 +319,7 @@ pub fn generate_all_levels(settings: &UiSettings) -> Vec { levels } +// Generates a single dungeon level from the UI settings. pub fn generate_level(settings: &UiSettings, level_index: usize) -> DungeonLayout { let level_seed = crate::seed::derive_seed(settings.seed, level_index as u64); let layout = layout::generate_layout( @@ -337,6 +342,7 @@ pub fn generate_level(settings: &UiSettings, level_index: usize) -> DungeonLayou populate_random_markers(layout, settings) } +// Clamps dependent settings. pub fn clamp_dependent_settings(settings: &mut UiSettings) { if settings.min_room_size > settings.max_room_size { settings.max_room_size = settings.min_room_size; @@ -377,6 +383,7 @@ pub fn clamp_dependent_settings(settings: &mut UiSettings) { } impl DungeonApp { + // Clears hover targets. pub fn clear_hover_targets(&mut self) { self.hover_room_idx = None; self.hover_corridor_idx = None; @@ -387,6 +394,7 @@ impl DungeonApp { self.hover_stair_idx = None; } + // Resets transient state. pub fn reset_transient_state(&mut self) { self.drag_state = None; self.add_corridor_drag = None; @@ -395,6 +403,7 @@ impl DungeonApp { self.pending_delete = false; } + // Captures the current app state for undo history. pub fn snapshot(&self) -> AppSnapshot { AppSnapshot { settings: self.settings.clone(), @@ -403,6 +412,7 @@ impl DungeonApp { } } + // Pushes undo snapshot. pub fn push_undo_snapshot(&mut self) { let snapshot = self.snapshot(); if self.undo_stack.last() == Some(&snapshot) { @@ -415,6 +425,7 @@ impl DungeonApp { self.redo_stack.clear(); } + // Restores a saved app state snapshot. pub fn restore_snapshot(&mut self, snapshot: AppSnapshot) { self.settings = snapshot.settings; self.levels = snapshot.levels; @@ -422,6 +433,7 @@ impl DungeonApp { self.reset_transient_state(); } + // Restores the previous undo snapshot. undo. pub fn undo(&mut self) { let Some(snapshot) = self.undo_stack.pop() else { return; @@ -430,6 +442,7 @@ impl DungeonApp { self.restore_snapshot(snapshot); } + // Restores the next redo snapshot. redo. pub fn redo(&mut self) { let Some(snapshot) = self.redo_stack.pop() else { return; @@ -438,6 +451,7 @@ impl DungeonApp { self.restore_snapshot(snapshot); } + // Clears all generated layout content and resets editing state. pub fn clear_layout(&mut self) { if self.settings.active_level_index >= self.levels.len() { return; @@ -448,6 +462,7 @@ impl DungeonApp { self.reset_transient_state(); } + // Switches to composition layout. pub fn enter_composition_layout(&mut self) { self.levels = vec![DungeonLayout::empty( self.settings.pack_rooms_without_corridors, @@ -458,6 +473,7 @@ impl DungeonApp { self.reset_transient_state(); } + // Regenerates every level from the current settings. pub fn regenerate_layout(&mut self) { self.drag_state = None; self.suppressed_auto_door_edges.clear(); @@ -468,6 +484,7 @@ impl DungeonApp { } } + // Deletes a level and keeps the active level index valid. pub fn delete_level(&mut self, level_idx: usize) { if self.levels.len() <= 1 { return; @@ -483,6 +500,7 @@ impl DungeonApp { self.reset_transient_state(); } + // Regenerates one level while preserving manual annotations where possible. pub fn refresh_level(&mut self, level_idx: usize) { if level_idx >= self.levels.len() { return; @@ -534,6 +552,7 @@ impl DungeonApp { ); } + // Recomputes staircase links across the current levels. pub fn refresh_stairs(&mut self) { let results = populate_stairs(self.levels.clone(), &self.settings); self.levels = results.iter().map(|(layout, _)| layout.clone()).collect(); @@ -545,6 +564,7 @@ impl DungeonApp { } } + // Recomputes generated doors while keeping manual doors. pub fn refresh_doors(&mut self) { if self.settings.active_level_index >= self.levels.len() { return; @@ -573,6 +593,7 @@ impl DungeonApp { } } +// Computes settings from ui. pub fn door_settings_from_ui(settings: &UiSettings) -> DoorSettings { DoorSettings { frequency_percent: settings.door_frequency_percent, @@ -583,6 +604,7 @@ pub fn door_settings_from_ui(settings: &UiSettings) -> DoorSettings { } } +// Computes settings from ui. pub fn window_settings_from_ui(settings: &UiSettings) -> WindowSettings { WindowSettings { enabled: settings.windows_enabled, diff --git a/src/exporter/mod.rs b/src/exporter/mod.rs index 8095b84..fe86f44 100644 --- a/src/exporter/mod.rs +++ b/src/exporter/mod.rs @@ -24,6 +24,7 @@ pub use types::*; type ProgressSender = mpsc::Sender; +// Selects export target. pub fn select_export_target(settings: &UiSettings) -> Result { if settings.export_format == ExportFormat::Folder || settings.export_level_index == 999 { let title = if settings.export_level_index == 999 { @@ -65,6 +66,7 @@ pub fn select_export_target(settings: &UiSettings) -> Result usize { match target { ExportTarget::File(_) => 1, @@ -122,6 +125,7 @@ fn export_image_count(settings: &UiSettings, target: &ExportTarget, level_count: } } +// Counts images per level. fn composite_images_per_level(settings: &UiSettings) -> usize { let base_masks = 12; let grid_mask = usize::from(settings.export_show_grid); @@ -129,10 +133,12 @@ fn composite_images_per_level(settings: &UiSettings) -> usize { base_masks + grid_mask + composite } +// Sends an export progress update to the UI channel. fn report_progress(progress_tx: &ProgressSender, completed: usize, total: usize) { let _ = progress_tx.send(ExportEvent::Progress(ExportProgress { completed, total })); } +// Exports level images to folder. fn export_level_images_to_folder( layouts: &[DungeonLayout], settings: &UiSettings, @@ -155,6 +161,7 @@ fn export_level_images_to_folder( }) } +// Saves layout to file. fn save_layout_to_file( layout: &DungeonLayout, settings: &UiSettings, @@ -182,6 +189,7 @@ fn save_layout_to_file( Ok(()) } +// Exports composite masks for levels. fn export_composite_masks_for_levels( layouts: &[DungeonLayout], settings: &UiSettings, @@ -265,6 +273,7 @@ fn export_composite_masks_for_levels( Ok(()) } +// Saves composite image. fn save_composite_image( context: &CompositeExportContext<'_>, settings: &UiSettings, @@ -285,6 +294,7 @@ fn save_composite_image( Ok(()) } +// Renders mask pixmap. fn render_mask_pixmap( context: &CompositeExportContext<'_>, task: MaskTask, @@ -441,6 +451,7 @@ fn render_mask_pixmap( Ok(result) } +// Creates an empty pixmap for a named export mask. fn blank_mask(g: &ExportGeometry, name: &str) -> Result { let mut pixmap = Pixmap::new(g.width, g.height) .ok_or_else(|| format!("Failed to allocate {name} mask canvas"))?; @@ -448,6 +459,7 @@ fn blank_mask(g: &ExportGeometry, name: &str) -> Result { Ok(pixmap) } +// Fills marker mask. fn fill_marker_mask( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -458,6 +470,7 @@ fn fill_marker_mask( } } +// Saves mask image. fn save_mask_image( folder: &std::path::Path, stem: &str, @@ -472,6 +485,7 @@ fn save_mask_image( Ok(()) } +// Selects image format. fn mask_image_format(format: MaskFormat) -> ImageFormat { match format { MaskFormat::Png => ImageFormat::Png, diff --git a/src/exporter/raster.rs b/src/exporter/raster.rs index c20d26a..e4a7d94 100644 --- a/src/exporter/raster.rs +++ b/src/exporter/raster.rs @@ -16,12 +16,14 @@ use image::{DynamicImage, RgbaImage, imageops::FilterType}; use std::collections::HashSet; use tiny_skia::{FillRule, Paint, PathBuilder, Pixmap, Rect, Stroke, StrokeDash, Transform}; +// Renders a dungeon layout into a raster pixmap. pub fn render_pixmap(layout: &DungeonLayout, settings: &UiSettings) -> Result { let g = ExportGeometry::new(settings.cols, settings.rows); let scene = collect_scene_data(layout, settings); render_pixmap_with_scene(layout, settings, &g, &scene) } +// Renders pixmap with scene. pub fn render_pixmap_with_scene( layout: &DungeonLayout, settings: &UiSettings, @@ -150,6 +152,7 @@ pub fn render_pixmap_with_scene( Ok(pixmap) } +// Fills the entire pixmap with a background color. pub fn fill_bg(pixmap: &mut Pixmap, color: (u8, u8, u8, u8)) { let mut paint = Paint::default(); paint.set_color_rgba8(color.0, color.1, color.2, color.3); @@ -160,6 +163,7 @@ pub fn fill_bg(pixmap: &mut Pixmap, color: (u8, u8, u8, u8)) { pixmap.fill_rect(rect, &paint, Transform::identity(), None); } +// Draws grid color. pub fn draw_grid_color(pixmap: &mut Pixmap, g: &ExportGeometry, color: (u8, u8, u8, u8)) { let left = g.left(); let top = g.top(); @@ -185,6 +189,7 @@ pub fn draw_grid_color(pixmap: &mut Pixmap, g: &ExportGeometry, color: (u8, u8, } } +// Fills rect cell. pub fn fill_rect_cell( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -200,6 +205,7 @@ pub fn fill_rect_cell( pixmap.fill_rect(rect, &paint, Transform::identity(), None); } +// Fills rect room. pub fn fill_rect_room( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -220,6 +226,7 @@ pub fn fill_rect_room( pixmap.fill_rect(rect, &paint, Transform::identity(), None); } +// Fills rect marker. pub fn fill_rect_marker( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -239,6 +246,7 @@ pub fn fill_rect_marker( pixmap.fill_rect(rect, &paint, Transform::identity(), None); } +// Draws area marker. pub fn draw_area_marker( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -374,6 +382,7 @@ pub fn draw_area_marker( } } +// Fills rect staircase. pub fn fill_rect_staircase( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -393,6 +402,7 @@ pub fn fill_rect_staircase( pixmap.fill_rect(rect, &paint, Transform::identity(), None); } +// Draws a staircase marker into the raster export. pub fn draw_staircase( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -451,6 +461,7 @@ pub fn draw_staircase( } } +// Draws staircase group. pub fn draw_staircase_group( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -463,6 +474,7 @@ pub fn draw_staircase_group( } } +// Draws area marker group. pub fn draw_area_marker_group( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -476,6 +488,7 @@ pub fn draw_area_marker_group( } } +// Draws a filled circular dot at a pixel position. pub fn draw_dot(pixmap: &mut Pixmap, cx: f32, cy: f32, radius: f32, color: (u8, u8, u8, u8)) { let mut pb = PathBuilder::new(); pb.push_circle(cx, cy, radius); @@ -493,6 +506,7 @@ pub fn draw_dot(pixmap: &mut Pixmap, cx: f32, cy: f32, radius: f32, color: (u8, ); } +// Draws room crosshatch. pub fn draw_room_crosshatch( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -529,6 +543,7 @@ pub fn draw_room_crosshatch( } } +// Draws cell walls. pub fn draw_cell_walls( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -611,6 +626,7 @@ pub fn draw_cell_walls( } } +// Draws wall segment. pub fn draw_wall_segment( pixmap: &mut Pixmap, x1: f32, @@ -647,6 +663,7 @@ pub fn draw_wall_segment( pixmap.fill_rect(rect, &paint, Transform::identity(), None); } +// Snaps even width. pub fn snap_even_width(value: f32) -> f32 { let mut w = value.round().max(1.0); if (w as u32) % 2 == 1 { @@ -655,6 +672,7 @@ pub fn snap_even_width(value: f32) -> f32 { w } +// Draws a styled door line onto the pixmap. pub fn draw_door( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -670,6 +688,7 @@ pub fn draw_door( draw_line(pixmap, x1, y1, x2, y2, width, color, style); } +// Draws a styled window line onto the pixmap. pub fn draw_window( pixmap: &mut Pixmap, g: &ExportGeometry, @@ -684,6 +703,7 @@ pub fn draw_window( draw_line(pixmap, x1, y1, x2, y2, width, color, style); } +// Draws a solid or patterned line segment. #[allow(clippy::too_many_arguments)] pub fn draw_line( pixmap: &mut Pixmap, @@ -707,6 +727,7 @@ pub fn draw_line( } } +// Strokes a path segment with an optional dash pattern. #[allow(clippy::too_many_arguments)] pub fn stroke_path( pixmap: &mut Pixmap, @@ -739,6 +760,7 @@ pub fn stroke_path( pixmap.stroke_path(&path, &paint, &stroke, Transform::identity(), None); } +// Handles dotted line. pub fn dotted_line( pixmap: &mut Pixmap, x1: f32, @@ -766,6 +788,7 @@ pub fn dotted_line( } } +// Handles raster image from pixmap. pub fn raster_image_from_pixmap( pixmap: &Pixmap, settings: &UiSettings, @@ -782,6 +805,7 @@ pub fn raster_image_from_pixmap( Ok(img) } +// Handles raster mask image from pixmap. pub fn raster_mask_image_from_pixmap( pixmap: &Pixmap, settings: &UiSettings, @@ -805,6 +829,7 @@ pub fn raster_mask_image_from_pixmap( Ok(DynamicImage::ImageRgba8(out)) } +// Handles raster target size. pub fn raster_target_size(settings: &UiSettings) -> (u32, u32) { let width = settings.export_width.clamp(1, 10_000); let mut height = settings.export_height.clamp(1, 10_000); diff --git a/src/exporter/svg.rs b/src/exporter/svg.rs index 7ef1d0d..5d927c2 100644 --- a/src/exporter/svg.rs +++ b/src/exporter/svg.rs @@ -14,6 +14,7 @@ use crate::ui::UiSettings; use std::collections::HashSet; use std::fmt::Write as _; +// Builds the complete SVG document for a dungeon layout. pub fn build_svg(layout: &DungeonLayout, settings: &UiSettings) -> String { let g = ExportGeometry::new(settings.cols, settings.rows); let wall_w = (g.cell / 2.5).max(1.0); @@ -253,6 +254,7 @@ pub fn build_svg(layout: &DungeonLayout, settings: &UiSettings) -> String { s } +// Appends svg walls. pub fn append_svg_walls( out: &mut String, g: &ExportGeometry, @@ -329,6 +331,7 @@ pub fn append_svg_walls( } } +// Appends svg area marker. pub fn append_svg_area_marker( out: &mut String, g: &ExportGeometry, @@ -419,6 +422,7 @@ pub fn append_svg_area_marker( } } +// Appends svg area marker group. pub fn append_svg_area_marker_group( out: &mut String, g: &ExportGeometry, diff --git a/src/exporter/types.rs b/src/exporter/types.rs index 2da88b6..a49377d 100644 --- a/src/exporter/types.rs +++ b/src/exporter/types.rs @@ -66,6 +66,7 @@ pub struct ExportGeometry { } impl ExportGeometry { + // Creates a new instance with the given inputs. pub fn new(cols: usize, rows: usize) -> Self { let cell = 64.0; let pad = 0.0; @@ -81,14 +82,17 @@ impl ExportGeometry { } } + // Returns the left edge of the export canvas. pub fn left(&self) -> f32 { self.pad } + // Returns the top edge of the export canvas. pub fn top(&self) -> f32 { self.pad } + // Returns the pixel rectangle for a grid cell. pub fn cell_rect(&self, col: usize, row: usize) -> Option { Rect::from_xywh( self.left() + col as f32 * self.cell, @@ -98,6 +102,7 @@ impl ExportGeometry { ) } + // Returns the pixel center point for a grid cell. pub fn cell_center(&self, col: usize, row: usize) -> (f32, f32) { ( self.left() + (col as f32 + 0.5) * self.cell, @@ -147,10 +152,12 @@ pub struct CompositeExportContext<'a> { pub door_width: f32, } +// Normalizes a cell edge so either endpoint order compares equal. pub fn norm_edge(a: Cell, b: Cell) -> CellEdge { if a <= b { (a, b) } else { (b, a) } } +// Computes edges for. pub fn door_edges_for(door: &Door, cols: usize, rows: usize) -> Vec { let mut edges = Vec::new(); if door.from.0.abs_diff(door.to.0) + door.from.1.abs_diff(door.to.1) != 1 { @@ -188,6 +195,7 @@ pub fn door_edges_for(door: &Door, cols: usize, rows: usize) -> Vec { edges } +// Computes render width. pub fn door_render_width(door: &Door) -> usize { if door.span_width { door.width.max(1) @@ -196,6 +204,7 @@ pub fn door_render_width(door: &Door) -> usize { } } +// Computes render width. pub fn window_render_width(window: &Window) -> usize { if window.span_width { window.width.max(1) diff --git a/src/exporter/utils.rs b/src/exporter/utils.rs index 57c0567..1c272cd 100644 --- a/src/exporter/utils.rs +++ b/src/exporter/utils.rs @@ -9,6 +9,7 @@ use crate::layout::{DungeonLayout, Room, Window, WindowSide, corridor_cells}; use crate::ui::UiSettings; use std::collections::HashSet; +// Collects scene data. pub fn collect_scene_data(layout: &DungeonLayout, settings: &UiSettings) -> SceneData { let mut scene = SceneData::default(); @@ -33,6 +34,7 @@ pub fn collect_scene_data(layout: &DungeonLayout, settings: &UiSettings) -> Scen scene } +// Computes edges from cells. pub fn corridor_edges_from_cells( corridor_cells: &HashSet<(usize, usize)>, ) -> HashSet<((usize, usize), (usize, usize))> { @@ -50,6 +52,7 @@ pub fn corridor_edges_from_cells( edges } +// Computes edges from rooms. pub fn room_edges_from_rooms(rooms: &[Room]) -> HashSet<((usize, usize), (usize, usize))> { let mut edges = HashSet::new(); for room in rooms { @@ -69,6 +72,7 @@ pub fn room_edges_from_rooms(rooms: &[Room]) -> HashSet<((usize, usize), (usize, edges } +// Computes line points. pub fn door_line_points( g: &ExportGeometry, a: (usize, usize), @@ -102,6 +106,7 @@ pub fn door_line_points( } } +// Computes line points. pub fn window_line_points(g: &ExportGeometry, window: &Window) -> Option<(f32, f32, f32, f32)> { let width_cells = window_render_width(window).max(1) as isize; let min_offset = -((width_cells - 1) / 2); diff --git a/src/interact/add_delete.rs b/src/interact/add_delete.rs index 7acb15b..38a9972 100644 --- a/src/interact/add_delete.rs +++ b/src/interact/add_delete.rs @@ -17,6 +17,7 @@ use crate::layout::{ use crate::ui::AddTool; use eframe::egui; +// Handles add tool. pub fn handle_add_tool(app: &mut DungeonApp, response: &egui::Response, geometry: &GridGeometry) { if app.settings.add_tool != AddTool::None && response.secondary_clicked() { app.settings.add_tool = AddTool::None; @@ -122,6 +123,7 @@ pub fn handle_add_tool(app: &mut DungeonApp, response: &egui::Response, geometry } } +// Deletes at pointer. pub fn delete_at_pointer(app: &mut DungeonApp, pointer_pos: egui::Pos2, geometry: &GridGeometry) { if app.settings.active_level_index >= app.levels.len() { return; @@ -236,6 +238,7 @@ pub fn delete_at_pointer(app: &mut DungeonApp, pointer_pos: egui::Pos2, geometry } } +// Adds room at cell. pub fn add_room_at_cell(app: &mut DungeonApp, cell: (usize, usize)) { app.push_undo_snapshot(); if app.settings.active_level_index >= app.levels.len() { @@ -275,6 +278,7 @@ pub fn add_room_at_cell(app: &mut DungeonApp, cell: (usize, usize)) { app.refresh_doors(); } +// Adds corridor between. pub fn add_corridor_between(app: &mut DungeonApp, start: (usize, usize), end: (usize, usize)) { app.push_undo_snapshot(); if app.settings.active_level_index >= app.levels.len() { @@ -319,6 +323,7 @@ pub fn add_corridor_between(app: &mut DungeonApp, start: (usize, usize), end: (u app.refresh_doors(); } +// Adds text at cell. pub fn add_text_at_cell(app: &mut DungeonApp, cell: (usize, usize)) { app.push_undo_snapshot(); if app.settings.active_level_index >= app.levels.len() { @@ -351,6 +356,7 @@ pub fn add_text_at_cell(app: &mut DungeonApp, cell: (usize, usize)) { }); } +// Adds marker at cell. pub fn add_marker_at_cell(app: &mut DungeonApp, cell: (usize, usize), kind: MarkerKind) { app.push_undo_snapshot(); if app.settings.active_level_index >= app.levels.len() { @@ -374,6 +380,7 @@ pub fn add_marker_at_cell(app: &mut DungeonApp, cell: (usize, usize), kind: Mark } } +// Adds staircase at cell. pub fn add_staircase_at_cell(app: &mut DungeonApp, cell: (usize, usize)) { app.push_undo_snapshot(); if app.settings.active_level_index >= app.levels.len() { @@ -416,6 +423,7 @@ pub fn add_staircase_at_cell(app: &mut DungeonApp, cell: (usize, usize)) { } } +// Deletes a room and removes dependent generated elements. pub fn delete_room(app: &mut DungeonApp, room_idx: usize) { if app.settings.active_level_index >= app.levels.len() { return; @@ -441,6 +449,7 @@ pub fn delete_room(app: &mut DungeonApp, room_idx: usize) { app.refresh_doors(); } +// Adds door at pointer. pub fn add_door_at_pointer( app: &mut DungeonApp, pointer_pos: egui::Pos2, @@ -525,6 +534,7 @@ pub fn add_door_at_pointer( app.suppressed_auto_door_edges.remove(&target); } +// Checks whether manual door edge allowed. pub fn manual_door_edge_allowed( a_room: Option, b_room: Option, diff --git a/src/interact/drag.rs b/src/interact/drag.rs index ced8e8f..f3beb60 100644 --- a/src/interact/drag.rs +++ b/src/interact/drag.rs @@ -14,6 +14,7 @@ use crate::layout::{blocked_room_cells, shortest_path_cells}; use crate::ui::AddTool; use eframe::egui; +// Handles active drag gestures for rooms, corridors, markers, stairs, and text. pub fn handle_drag( app: &mut DungeonApp, ctx: &egui::Context, @@ -80,6 +81,7 @@ pub fn handle_drag( } } +// Drags room to pointer. pub fn drag_room_to_pointer( app: &mut DungeonApp, drag: RoomDragState, @@ -121,6 +123,7 @@ pub fn drag_room_to_pointer( app.refresh_doors(); } +// Drags text to pointer. pub fn drag_text_to_pointer( app: &mut DungeonApp, drag: TextDragState, @@ -152,6 +155,7 @@ pub fn drag_text_to_pointer( app.levels[app.settings.active_level_index].text_labels[drag.text_idx].cell = target; } +// Reroutes corridors for room. pub fn reroute_corridors_for_room(app: &mut DungeonApp, room_idx: usize) { if app.settings.active_level_index >= app.levels.len() { return; @@ -181,6 +185,7 @@ pub fn reroute_corridors_for_room(app: &mut DungeonApp, room_idx: usize) { } } +// Drags corridor to pointer. pub fn drag_corridor_to_pointer( app: &mut DungeonApp, drag: CorridorDragState, @@ -225,6 +230,7 @@ pub fn drag_corridor_to_pointer( app.refresh_doors(); } +// Drags marker to pointer. pub fn drag_marker_to_pointer( app: &mut DungeonApp, drag: MarkerDragState, @@ -258,6 +264,7 @@ pub fn drag_marker_to_pointer( marker.cell = (target_x.min(max_x), target_y.min(max_y)); } +// Drags stair to pointer. pub fn drag_stair_to_pointer( app: &mut DungeonApp, drag: StaircaseDragState, diff --git a/src/interact/mod.rs b/src/interact/mod.rs index 92a5f2b..eb2d9db 100644 --- a/src/interact/mod.rs +++ b/src/interact/mod.rs @@ -28,6 +28,7 @@ pub struct GridGeometry { pub rows: usize, } +// Draws the editable grid and returns its screen geometry. pub fn draw_grid( painter: &egui::Painter, area: egui::Rect, @@ -82,6 +83,7 @@ pub fn draw_grid( } } +// Handles update hover targets. pub fn update_hover_targets(app: &mut DungeonApp, ctx: &egui::Context, geometry: &GridGeometry) { if app.drag_state.is_some() || app.resize_state.is_some() || app.add_corridor_drag.is_some() { return; @@ -158,6 +160,7 @@ pub fn update_hover_targets(app: &mut DungeonApp, ctx: &egui::Context, geometry: } } +// Computes edge at pointer. pub fn door_edge_at_pointer( app: &DungeonApp, pointer_pos: egui::Pos2, @@ -210,6 +213,7 @@ pub fn door_edge_at_pointer( Some(((ax as usize, ay as usize), (bx as usize, by as usize))) } +// Computes at pointer. pub fn room_at_pointer( app: &DungeonApp, pointer_pos: egui::Pos2, @@ -236,6 +240,7 @@ pub fn room_at_pointer( None } +// Computes at pointer. pub fn text_at_pointer( app: &DungeonApp, pointer_pos: egui::Pos2, @@ -254,6 +259,7 @@ pub fn text_at_pointer( .position(|label| label.cell == clicked) } +// Computes at pointer. pub fn marker_at_pointer( app: &DungeonApp, pointer_pos: egui::Pos2, @@ -298,6 +304,7 @@ pub fn marker_at_pointer( }) } +// Computes drag at pointer. pub fn marker_drag_at_pointer( app: &DungeonApp, pointer_pos: egui::Pos2, @@ -349,6 +356,7 @@ pub fn marker_drag_at_pointer( } } +// Handles stair at pointer. pub fn stair_at_pointer( app: &DungeonApp, pointer_pos: egui::Pos2, @@ -369,6 +377,7 @@ pub fn stair_at_pointer( }) } +// Handles stair drag at pointer. pub fn stair_drag_at_pointer( app: &DungeonApp, pointer_pos: egui::Pos2, @@ -390,6 +399,7 @@ pub fn stair_drag_at_pointer( }) } +// Resizes room at pointer. pub fn resize_room_at_pointer( app: &DungeonApp, pointer_pos: egui::Pos2, @@ -421,6 +431,7 @@ pub fn resize_room_at_pointer( None } +// Computes drag at pointer. pub fn corridor_drag_at_pointer( app: &DungeonApp, pointer_pos: egui::Pos2, @@ -445,6 +456,7 @@ pub fn corridor_drag_at_pointer( }) } +// Converts to grid. pub fn pointer_to_grid(pointer_pos: egui::Pos2, geometry: &GridGeometry) -> Option<(f32, f32)> { if !geometry.rect.contains(pointer_pos) { return None; @@ -455,6 +467,7 @@ pub fn pointer_to_grid(pointer_pos: egui::Pos2, geometry: &GridGeometry) -> Opti Some((x, y)) } +// Reroutes path through cell. pub fn reroute_path_through_cell( original_path: &[(usize, usize)], original_cell: (usize, usize), @@ -512,6 +525,7 @@ pub fn reroute_path_through_cell( Some(full_path) } +// Simplifies path loops. pub fn simplify_path_loops(path: &mut Vec<(usize, usize)>) { let mut out = Vec::new(); for &cell in path.iter() { @@ -524,6 +538,7 @@ pub fn simplify_path_loops(path: &mut Vec<(usize, usize)>) { *path = out; } +// Resizes hit cells. pub fn resize_hit_cells( room: &layout::Room, room_idx: usize, @@ -587,6 +602,7 @@ pub fn resize_hit_cells( cells } +// Computes edges for. pub fn door_edges_for( door: &layout::Door, cols: usize, @@ -628,6 +644,7 @@ pub fn door_edges_for( edges } +// Computes render width. pub fn door_render_width(door: &layout::Door) -> usize { if door.span_width { door.width.max(1) @@ -636,6 +653,7 @@ pub fn door_render_width(door: &layout::Door) -> usize { } } +// Computes render width. pub fn window_render_width(window: &layout::Window) -> usize { if window.span_width { window.width.max(1) @@ -644,10 +662,12 @@ pub fn window_render_width(window: &layout::Window) -> usize { } } +// Normalizes a cell edge so either endpoint order compares equal. pub fn normalized_edge(a: (usize, usize), b: (usize, usize)) -> ((usize, usize), (usize, usize)) { if a <= b { (a, b) } else { (b, a) } } +// Returns the screen center point for a grid cell. pub fn cell_center(geometry: &GridGeometry, col: usize, row: usize) -> egui::Pos2 { egui::pos2( geometry.rect.left() + (col as f32 + 0.5) * geometry.cell_size, @@ -655,6 +675,7 @@ pub fn cell_center(geometry: &GridGeometry, col: usize, row: usize) -> egui::Pos ) } +// Returns the screen rectangle for a grid cell. pub fn cell_rect(geometry: &GridGeometry, col: usize, row: usize) -> egui::Rect { let left = geometry.rect.left() + col as f32 * geometry.cell_size; let top = geometry.rect.top() + row as f32 * geometry.cell_size; @@ -664,6 +685,7 @@ pub fn cell_rect(geometry: &GridGeometry, col: usize, row: usize) -> egui::Rect ) } +// Computes the screen rectangle occupied by an area marker. pub fn marker_rect(marker: &layout::AreaMarker, geometry: &GridGeometry) -> egui::Rect { let left = geometry.rect.left() + marker.cell.0 as f32 * geometry.cell_size; let top = geometry.rect.top() + marker.cell.1 as f32 * geometry.cell_size; @@ -676,6 +698,7 @@ pub fn marker_rect(marker: &layout::AreaMarker, geometry: &GridGeometry) -> egui ) } +// Computes contains cell. pub fn marker_contains_cell(marker: Option<&layout::AreaMarker>, cell: (usize, usize)) -> bool { let Some(marker) = marker else { return false; @@ -686,6 +709,7 @@ pub fn marker_contains_cell(marker: Option<&layout::AreaMarker>, cell: (usize, u && cell.1 < marker.cell.1 + marker.size } +// Computes marker origin. pub fn centered_marker_origin( cell: (usize, usize), size: usize, @@ -702,6 +726,7 @@ pub fn centered_marker_origin( ) } +// Draws add overlay. pub fn draw_add_overlay(app: &DungeonApp, painter: &egui::Painter, geometry: &GridGeometry) { if app.settings.add_tool != AddTool::Corridor { return; @@ -717,6 +742,7 @@ pub fn draw_add_overlay(app: &DungeonApp, painter: &egui::Painter, geometry: &Gr crate::rendering::draw_dashed_line(painter, start, end, stroke, 8.0, 6.0); } +// Draws add tool ghost. pub fn draw_add_tool_ghost(app: &DungeonApp, painter: &egui::Painter, geometry: &GridGeometry) { let tool = app.settings.add_tool; if tool == AddTool::None || tool == AddTool::Corridor { @@ -915,6 +941,7 @@ pub fn draw_add_tool_ghost(app: &DungeonApp, painter: &egui::Painter, geometry: } } +// Draws resize overlay. pub fn draw_resize_overlay(app: &DungeonApp, painter: &egui::Painter, geometry: &GridGeometry) { if app.settings.active_level_index >= app.levels.len() { return; @@ -969,6 +996,7 @@ pub fn draw_resize_overlay(app: &DungeonApp, painter: &egui::Painter, geometry: } } +// Draws room resize visuals. pub fn draw_room_resize_visuals( painter: &egui::Painter, geometry: &GridGeometry, @@ -1013,6 +1041,7 @@ pub fn draw_room_resize_visuals( } } +// Draws staircase resize visuals. pub fn draw_staircase_resize_visuals( painter: &egui::Painter, geometry: &GridGeometry, @@ -1045,6 +1074,7 @@ pub fn draw_staircase_resize_visuals( } } +// Draws corridor hover overlay. pub fn draw_corridor_hover_overlay( app: &DungeonApp, painter: &egui::Painter, @@ -1071,6 +1101,7 @@ pub fn draw_corridor_hover_overlay( } } +// Draws door hover overlay. pub fn draw_door_hover_overlay(app: &DungeonApp, painter: &egui::Painter, geometry: &GridGeometry) { let Some(idx) = app.hover_door_idx else { return; @@ -1096,6 +1127,7 @@ pub fn draw_door_hover_overlay(app: &DungeonApp, painter: &egui::Painter, geomet ); } +// Draws resize handle. pub fn draw_resize_handle( painter: &egui::Painter, corner: egui::Pos2, diff --git a/src/interact/resize.rs b/src/interact/resize.rs index 9966363..70582d7 100644 --- a/src/interact/resize.rs +++ b/src/interact/resize.rs @@ -13,6 +13,7 @@ use crate::layout::{rects_overlap, rooms_overlap}; use crate::ui::AddTool; use eframe::egui; +// Handles secondary-button resize gestures for resizable layout elements. pub fn handle_resize( app: &mut DungeonApp, ctx: &egui::Context, @@ -71,6 +72,7 @@ pub fn handle_resize( false } +// Starts text resize. pub fn start_text_resize(app: &DungeonApp, text_idx: usize) -> Option { if app.settings.active_level_index >= app.levels.len() { return None; @@ -85,6 +87,7 @@ pub fn start_text_resize(app: &DungeonApp, text_idx: usize) -> Option= app.levels.len() { return; @@ -207,6 +212,7 @@ pub fn resize_room(app: &mut DungeonApp, state: &RoomResizeState, target_cell: ( } } +// Resizes a text label based on the drag target cell. pub fn resize_text(app: &mut DungeonApp, state: &TextResizeState, target_cell: (usize, usize)) { if app.settings.active_level_index >= app.levels.len() { return; @@ -225,6 +231,7 @@ pub fn resize_text(app: &mut DungeonApp, state: &TextResizeState, target_cell: ( label.font_size = new_size as u16; } +// Resizes a staircase while clamping it to the grid. pub fn resize_staircase( app: &mut DungeonApp, state: &StaircaseResizeState, diff --git a/src/layout/generation/connections.rs b/src/layout/generation/connections.rs index 0997d73..11c11d3 100644 --- a/src/layout/generation/connections.rs +++ b/src/layout/generation/connections.rs @@ -14,6 +14,7 @@ pub type Cell = (usize, usize); pub type CellEdge = (Cell, Cell); pub type RoomBoundary = (usize, usize, Vec); +// Builds room connection edges. pub fn build_room_connection_edges( centers: &[(usize, usize)], randomness: f32, @@ -73,6 +74,7 @@ pub fn build_room_connection_edges( edges } +// Orders core rooms. pub fn ordered_core_rooms( core_rooms: &[usize], centers: &[(usize, usize)], @@ -107,6 +109,7 @@ pub fn ordered_core_rooms( ordered } +// Pushes unique room edge. pub fn push_unique_room_edge( a: usize, b: usize, @@ -122,6 +125,7 @@ pub fn push_unique_room_edge( } } +// Computes exit edge. pub fn room_exit_edge( path: &[(usize, usize)], room: &Room, @@ -151,6 +155,7 @@ pub fn room_exit_edge( None } +// Computes collision edges. pub fn room_collision_edges( path: &[(usize, usize)], room: &Room, @@ -180,6 +185,7 @@ pub fn room_collision_edges( edges } +// Finds room boundaries. pub fn shared_room_boundaries(rooms: &[Room]) -> Vec { let mut boundaries = Vec::new(); for a_idx in 0..rooms.len() { diff --git a/src/layout/generation/markers.rs b/src/layout/generation/markers.rs index 797a2cf..3f050a0 100644 --- a/src/layout/generation/markers.rs +++ b/src/layout/generation/markers.rs @@ -10,6 +10,7 @@ use crate::seed; use crate::ui::UiSettings; use std::collections::HashSet; +// Populates random markers. pub fn populate_random_markers(mut layout: DungeonLayout, settings: &UiSettings) -> DungeonLayout { layout.start_markers.clear(); layout.end_markers.clear(); @@ -86,6 +87,7 @@ pub fn populate_random_markers(mut layout: DungeonLayout, settings: &UiSettings) layout } +// Generates range inclusive. pub fn random_range_inclusive(min: usize, max: usize, seed_value: u64) -> usize { let min = min.max(1); let max = max.max(min); @@ -93,6 +95,7 @@ pub fn random_range_inclusive(min: usize, max: usize, seed_value: u64) -> usize min + (seed_value as usize % span) } +// Computes in room. pub fn marker_in_room( room: &Room, min_size: usize, @@ -120,6 +123,7 @@ pub fn marker_in_room( AreaMarker { cell: (x, y), size } } +// Handles assign extra markers. #[allow(clippy::too_many_arguments)] pub fn assign_extra_markers( markers: &mut Vec, @@ -149,6 +153,7 @@ pub fn assign_extra_markers( } } +// Finds room pair. pub fn farthest_room_pair( rooms: &[Room], available_start_rooms: &[usize], @@ -182,6 +187,7 @@ pub fn farthest_room_pair( best } +// Computes distance sq. pub fn room_distance_sq(a: &Room, b: &Room) -> usize { let ac = a.center_cell(); let bc = b.center_cell(); @@ -190,12 +196,14 @@ pub fn room_distance_sq(a: &Room, b: &Room) -> usize { dx * dx + dy * dy } +// Removes a room id from the available marker placement list. pub fn consume_room(available_rooms: &mut Vec, room_idx: usize) { if let Some(pos) = available_rooms.iter().position(|&idx| idx == room_idx) { available_rooms.remove(pos); } } +// Picks room index. pub fn pick_room_index(available_rooms: &[usize], room_count: usize, seed_value: u64) -> usize { if !available_rooms.is_empty() { available_rooms[seed_value as usize % available_rooms.len()] @@ -204,6 +212,7 @@ pub fn pick_room_index(available_rooms: &[usize], room_count: usize, seed_value: } } +// Populates random traps. pub fn populate_random_traps(mut layout: DungeonLayout, settings: &UiSettings) -> DungeonLayout { layout.trap_markers = populate_random_area_markers( &layout, @@ -217,6 +226,7 @@ pub fn populate_random_traps(mut layout: DungeonLayout, settings: &UiSettings) - layout } +// Populates random monsters. pub fn populate_random_monsters(mut layout: DungeonLayout, settings: &UiSettings) -> DungeonLayout { layout.monster_markers = populate_random_area_markers( &layout, @@ -230,6 +240,7 @@ pub fn populate_random_monsters(mut layout: DungeonLayout, settings: &UiSettings layout } +// Populates random area markers. pub fn populate_random_area_markers( layout: &DungeonLayout, master_seed: u64, @@ -272,6 +283,7 @@ pub fn populate_random_area_markers( markers } +// Appends room markers. pub fn append_room_markers( markers: &mut Vec, room: &Room, @@ -295,6 +307,7 @@ pub fn append_room_markers( } } +// Appends corridor markers. pub fn append_corridor_markers( markers: &mut Vec, corridor: &Corridor, @@ -317,10 +330,12 @@ pub fn append_corridor_markers( } } +// Checks whether passes frequency roll. pub fn passes_frequency_roll(area_seed: u64, frequency_percent: usize) -> bool { (area_seed % 100) < frequency_percent as u64 } +// Picks random corridor cell. pub fn pick_random_corridor_cell(corridor: &Corridor, seed_value: u64) -> Option<(usize, usize)> { if corridor.path.is_empty() { return None; @@ -329,6 +344,7 @@ pub fn pick_random_corridor_cell(corridor: &Corridor, seed_value: u64) -> Option Some(corridor.path[idx]) } +// Populates staircase transitions between generated levels. pub fn populate_stairs( mut layouts: Vec, settings: &UiSettings, @@ -396,6 +412,7 @@ pub fn populate_stairs( result } +// Gets stair count. pub fn get_stair_count(settings: &UiSettings, gap_idx: usize) -> usize { if settings.min_stairs_per_level == settings.max_stairs_per_level { settings.min_stairs_per_level @@ -406,6 +423,7 @@ pub fn get_stair_count(settings: &UiSettings, gap_idx: usize) -> usize { } } +// Ensures stair in room. pub fn ensure_stair_in_room(layout: &mut DungeonLayout, stair: &Staircase) -> bool { let stair_x = stair.cell.0; let stair_y = stair.cell.1; @@ -458,6 +476,7 @@ pub fn ensure_stair_in_room(layout: &mut DungeonLayout, stair: &Staircase) -> bo } } +// Computes to stair min dist. pub fn room_to_stair_min_dist(room: &Room, stair: &Staircase) -> usize { let dx = if stair.cell.0 + stair.width <= room.x { room.x - (stair.cell.0 + stair.width) @@ -474,6 +493,7 @@ pub fn room_to_stair_min_dist(room: &Room, stair: &Staircase) -> usize { dx + dy } +// Picks stair positions. pub fn pick_stair_positions( layout: &DungeonLayout, settings: &UiSettings, @@ -548,6 +568,7 @@ pub fn pick_stair_positions( .collect() } +// Checks whether has start or end on bottom row. pub fn has_start_or_end_on_bottom_row( room: &Room, start_markers: &[AreaMarker], @@ -563,6 +584,7 @@ pub fn has_start_or_end_on_bottom_row( false } +// Generates stair size. pub fn random_stair_size(settings: &UiSettings, seed_value: u64) -> (usize, usize) { let w_span = settings .max_stair_width @@ -590,10 +612,12 @@ pub struct StairShuffleRng { } impl StairShuffleRng { + // Creates a new instance with the given inputs. pub fn new(seed: u64) -> Self { Self { state: seed } } + // Generates the next pseudo-random 32-bit value. pub fn next_u32(&mut self) -> u32 { self.state = self .state diff --git a/src/layout/generation/mod.rs b/src/layout/generation/mod.rs index be5590f..dda3f7c 100644 --- a/src/layout/generation/mod.rs +++ b/src/layout/generation/mod.rs @@ -18,6 +18,7 @@ pub use markers::*; pub use passages::*; pub use room_placement::*; +// Generates a complete dungeon layout from generation settings. #[allow(clippy::too_many_arguments)] pub fn generate_layout( cols: usize, diff --git a/src/layout/generation/passages.rs b/src/layout/generation/passages.rs index 2d4f479..6a0805b 100644 --- a/src/layout/generation/passages.rs +++ b/src/layout/generation/passages.rs @@ -14,6 +14,7 @@ use super::connections::{room_collision_edges, room_exit_edge, shared_room_bound use crate::seed; use std::collections::HashSet; +// Applies generated doors and archways to room-corridor transitions. pub fn apply_doors( layout: &mut DungeonLayout, seed: u64, @@ -139,6 +140,7 @@ pub fn apply_doors( apply_secret_doors(layout, seed, settings); } +// Applies packed room doors. pub fn apply_packed_room_doors(layout: &mut DungeonLayout, seed: u64, settings: DoorSettings) { let mut rng = SimpleRng::new(seed::derive_seed(seed, 0xD005_5EED_u64)); let door_chance = ((settings.frequency_percent.min(100) as f32) / 100.0) @@ -175,6 +177,7 @@ pub fn apply_packed_room_doors(layout: &mut DungeonLayout, seed: u64, settings: apply_secret_doors(layout, seed, settings); } +// Applies secret doors. pub fn apply_secret_doors(layout: &mut DungeonLayout, seed: u64, settings: DoorSettings) { let secret_percent = settings.secret_percent.min(100); let chance = (secret_percent as f32) / 100.0; @@ -206,6 +209,7 @@ pub fn apply_secret_doors(layout: &mut DungeonLayout, seed: u64, settings: DoorS } } +// Computes is secret eligible for rooms. pub fn door_is_secret_eligible_for_rooms( layout: &DungeonLayout, room_door_map: &[Vec], @@ -230,6 +234,7 @@ pub fn door_is_secret_eligible_for_rooms( true } +// Computes to door indices. pub fn room_to_door_indices(layout: &DungeonLayout) -> Vec> { let mut room_door_map = vec![Vec::new(); layout.rooms.len()]; for (door_idx, door) in layout.doors.iter().enumerate() { @@ -242,6 +247,7 @@ pub fn room_to_door_indices(layout: &DungeonLayout) -> Vec> { room_door_map } +// Handles secret room ids. pub fn secret_room_ids(layout: &DungeonLayout) -> HashSet { let mut secret_rooms = HashSet::new(); for door in layout.doors.iter().filter(|door| door.secret) { @@ -254,10 +260,12 @@ pub fn secret_room_ids(layout: &DungeonLayout) -> HashSet { secret_rooms } +// Computes touches room. pub fn door_touches_room(door: &Door, room: &Room) -> bool { cell_in_room(door.from, room) || cell_in_room(door.to, room) } +// Computes directly connects rooms. pub fn door_directly_connects_rooms(layout: &DungeonLayout, door_idx: usize) -> bool { let Some(door) = layout.doors.get(door_idx) else { return false; @@ -273,6 +281,7 @@ pub fn door_directly_connects_rooms(layout: &DungeonLayout, door_idx: usize) -> touching_rooms.len() >= 2 } +// Builds in room. pub fn cell_in_room(cell: (usize, usize), room: &Room) -> bool { cell.0 >= room.x && cell.0 < room.x + room.width @@ -280,6 +289,7 @@ pub fn cell_in_room(cell: (usize, usize), room: &Room) -> bool { && cell.1 < room.y + room.height } +// Applies generated windows to eligible room boundaries. pub fn apply_windows( layout: &mut DungeonLayout, seed: u64, @@ -341,6 +351,7 @@ pub enum WindowTarget { Room(usize), } +// Collects window segments. pub fn collect_window_segments( layout: &DungeonLayout, cols: usize, @@ -404,6 +415,7 @@ pub fn collect_window_segments( segments } +// Collects room side segments. #[allow(clippy::too_many_arguments)] pub fn collect_room_side_segments( room_idx: usize, @@ -467,6 +479,7 @@ pub fn collect_room_side_segments( push_window_segment(current_target, side, &mut current_cells, segments); } +// Pushes window segment. pub fn push_window_segment( target: Option, side: WindowSide, @@ -488,6 +501,7 @@ pub fn push_window_segment( }); } +// Finds the grid cell outside a room side. pub fn outward_neighbor( cell: (usize, usize), side: WindowSide, @@ -502,6 +516,7 @@ pub fn outward_neighbor( } } +// Selects segment cell. pub fn select_segment_cell( cells: &[(usize, usize)], width: usize, diff --git a/src/layout/generation/room_placement.rs b/src/layout/generation/room_placement.rs index a291226..a92f175 100644 --- a/src/layout/generation/room_placement.rs +++ b/src/layout/generation/room_placement.rs @@ -8,6 +8,7 @@ use super::super::types::Room; use super::super::utils::{SimpleRng, rooms_overlap, rooms_touch, shuffle_indices}; use std::collections::VecDeque; +// Generates room sizes. pub fn generate_room_sizes( target_room_count: usize, cols: usize, @@ -48,6 +49,7 @@ pub fn generate_room_sizes( sizes } +// Generates random room center points inside the grid. pub fn random_centers( count: usize, cols: usize, @@ -64,6 +66,7 @@ pub fn random_centers( centers } +// Places packed rooms. pub fn place_packed_rooms( room_sizes: &[(usize, usize)], room_edges: &[(usize, usize)], @@ -116,6 +119,7 @@ pub fn place_packed_rooms( placed.into_iter().flatten().collect() } +// Computes the order used to place packed rooms. pub fn placement_order(room_count: usize, room_edges: &[(usize, usize)]) -> Vec { if room_count == 0 { return Vec::new(); @@ -152,6 +156,7 @@ pub fn placement_order(room_count: usize, room_edges: &[(usize, usize)]) -> Vec< order } +// Tries to place packed room. pub fn try_place_packed_room( room_idx: usize, room_sizes: &[(usize, usize)], @@ -214,6 +219,7 @@ pub fn try_place_packed_room( None } +// Builds room candidates. pub fn packed_room_candidates( anchor: &Room, width: usize, @@ -261,6 +267,7 @@ pub fn packed_room_candidates( candidates } +// Shuffles rooms with the deterministic layout RNG. pub fn shuffle_rooms(rooms: &mut [Room], rng: &mut SimpleRng) { if rooms.len() <= 1 { return; diff --git a/src/layout/utils.rs b/src/layout/utils.rs index 70abe54..92b810f 100644 --- a/src/layout/utils.rs +++ b/src/layout/utils.rs @@ -181,6 +181,7 @@ pub fn corridor_cells(layout: &DungeonLayout, cols: usize, rows: usize) -> HashS cells } +// Computes index at cell. pub fn room_index_at_cell(rooms: &[Room], cell: (usize, usize)) -> Option { rooms.iter().position(|room| { cell.0 >= room.x @@ -218,6 +219,7 @@ pub fn overlaps_with_padding(a: &Room, b: &Room, padding: usize) -> bool { a_left < b_right && a_right > b_left && a_top < b_bottom && a_bottom > b_top } +// Checks whether rects overlap. #[allow(clippy::too_many_arguments)] pub fn rects_overlap( ax: usize, @@ -237,14 +239,17 @@ pub fn rects_overlap( ax < b_right && a_right > bx && ay < b_bottom && a_bottom > by } +// Checks whether rooms overlap. pub fn rooms_overlap(a: &Room, b: &Room) -> bool { rects_overlap(a.x, a.y, a.width, a.height, b.x, b.y, b.width, b.height) } +// Checks whether rooms touch. pub fn rooms_touch(a: &Room, b: &Room) -> bool { !shared_boundary_edges(a, b).is_empty() } +// Finds boundary edges. pub fn shared_boundary_edges(a: &Room, b: &Room) -> Vec<((usize, usize), (usize, usize))> { let mut edges = Vec::new(); @@ -277,6 +282,7 @@ pub fn shared_boundary_edges(a: &Room, b: &Room) -> Vec<((usize, usize), (usize, edges } +// Finds opening width. pub fn shared_opening_width(a: &Room, b: &Room, span: usize, default_width: usize) -> usize { let max_width = if a.x + a.width == b.x || b.x + b.width == a.x { a.height.min(b.height) diff --git a/src/rendering.rs b/src/rendering.rs index f325794..34007b4 100644 --- a/src/rendering.rs +++ b/src/rendering.rs @@ -13,6 +13,7 @@ use eframe::egui; use egui::{Color32, Stroke}; use std::collections::HashSet; +// Draws the full dungeon layout into the interactive canvas. pub fn draw_layout( painter: &egui::Painter, geometry: &GridGeometry, @@ -325,6 +326,7 @@ pub fn draw_layout( } } +// Draws a staircase marker into the interactive canvas. pub fn draw_staircase( painter: &egui::Painter, geometry: &GridGeometry, @@ -380,6 +382,7 @@ pub fn draw_staircase( } } +// Computes label rect. pub fn text_label_rect(geometry: &GridGeometry, label: &crate::layout::TextLabel) -> egui::Rect { let center = cell_center(geometry, label.cell.0, label.cell.1); let font_size = label.font_size as f32; @@ -389,6 +392,7 @@ pub fn text_label_rect(geometry: &GridGeometry, label: &crate::layout::TextLabel egui::Rect::from_center_size(center, egui::vec2(width, height)) } +// Draws area marker. pub fn draw_area_marker( painter: &egui::Painter, geometry: &GridGeometry, @@ -430,6 +434,7 @@ pub fn draw_area_marker( ); } +// Draws area marker group. #[allow(clippy::too_many_arguments)] pub fn draw_area_marker_group( painter: &egui::Painter, @@ -461,6 +466,7 @@ pub fn draw_area_marker_group( } } +// Draws wall segment. pub fn draw_wall_segment( painter: &egui::Painter, from: egui::Pos2, @@ -490,6 +496,7 @@ pub fn draw_wall_segment( } } +// Computes edges from cells. pub fn corridor_edges_from_cells( corridor_cells: &HashSet<(usize, usize)>, ) -> HashSet<((usize, usize), (usize, usize))> { @@ -507,6 +514,7 @@ pub fn corridor_edges_from_cells( edges } +// Computes edges from rooms. pub fn room_edges_from_rooms( rooms: &[crate::layout::Room], ) -> HashSet<((usize, usize), (usize, usize))> { @@ -538,6 +546,7 @@ pub enum DoorLineStyle { DashDotDot, } +// Draws door line. pub fn draw_door_line( painter: &egui::Painter, geometry: &GridGeometry, @@ -574,6 +583,7 @@ pub fn draw_door_line( } } +// Draws window line. pub fn draw_window_line( painter: &egui::Painter, geometry: &GridGeometry, @@ -625,6 +635,7 @@ pub fn draw_window_line( } } +// Draws styled line. pub fn draw_styled_line( painter: &egui::Painter, from: egui::Pos2, @@ -644,6 +655,7 @@ pub fn draw_styled_line( } } +// Draws dashed line. pub fn draw_dashed_line( painter: &egui::Painter, from: egui::Pos2, @@ -672,6 +684,7 @@ pub fn draw_dashed_line( } } +// Draws dotted line. pub fn draw_dotted_line(painter: &egui::Painter, from: egui::Pos2, to: egui::Pos2, stroke: Stroke) { let dx = to.x - from.x; let dy = to.y - from.y; @@ -692,6 +705,7 @@ pub fn draw_dotted_line(painter: &egui::Painter, from: egui::Pos2, to: egui::Pos } } +// Draws dash dot line. pub fn draw_dash_dot_line( painter: &egui::Painter, from: egui::Pos2, @@ -723,6 +737,7 @@ pub fn draw_dash_dot_line( } } +// Draws dash dot dot line. pub fn draw_dash_dot_dot_line( painter: &egui::Painter, from: egui::Pos2, @@ -761,6 +776,7 @@ pub fn draw_dash_dot_dot_line( } } +// Draws room crosshatch. pub fn draw_room_crosshatch( painter: &egui::Painter, geometry: &GridGeometry, diff --git a/src/saveandload.rs b/src/saveandload.rs index cbc2657..efbdada 100644 --- a/src/saveandload.rs +++ b/src/saveandload.rs @@ -19,6 +19,7 @@ pub struct DungeonSave { pub svgs: Vec, } +// Saves dungeon state to a user-selected JSON file. pub fn save_dungeon( settings: &UiSettings, layouts: Vec, @@ -45,6 +46,7 @@ pub fn save_dungeon( Ok(path) } +// Loads dungeon state from a user-selected JSON file. pub fn load_dungeon() -> Result { let path = FileDialog::new() .set_title("Load Dungeon State") diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 66994cd..2d9bf0d 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -19,6 +19,7 @@ pub enum Tab { } impl Default for Tab { + // Provides default settings for this type. fn default() -> Self { Self::Generate } @@ -34,12 +35,14 @@ pub enum ExportFormat { } impl Default for ExportFormat { + // Provides default settings for this type. fn default() -> Self { Self::Png } } impl ExportFormat { + // Returns the file extension for this format. pub fn extension(self) -> &'static str { match self { ExportFormat::Png => "png", @@ -50,6 +53,7 @@ impl ExportFormat { } } + // Returns the user-facing label for this option. pub fn label(self) -> &'static str { match self { ExportFormat::Png => ".png", @@ -60,6 +64,7 @@ impl ExportFormat { } } + // Reports whether this format supports resolution scaling. pub fn supports_resolution(self) -> bool { !matches!(self, ExportFormat::Svg) } @@ -73,12 +78,14 @@ pub enum MaskFormat { } impl Default for MaskFormat { + // Provides default settings for this type. fn default() -> Self { Self::Png } } impl MaskFormat { + // Returns the file extension for this format. pub fn extension(self) -> &'static str { match self { MaskFormat::Png => "png", @@ -87,6 +94,7 @@ impl MaskFormat { } } + // Returns the user-facing label for this option. pub fn label(self) -> &'static str { match self { MaskFormat::Png => ".png", @@ -169,6 +177,7 @@ pub struct UiSettings { } impl Default for UiSettings { + // Provides default settings for this type. fn default() -> Self { UiSettings { seed: 0, @@ -270,6 +279,7 @@ pub struct SidePanelResult { pub new_level_clicked: bool, } +// Draws side panel. pub fn draw_side_panel( ctx: &egui::Context, settings: &mut UiSettings, @@ -343,6 +353,7 @@ pub fn draw_side_panel( result } +// Draws legend panel. pub fn draw_legend_panel(ctx: &egui::Context, settings: &mut UiSettings) -> bool { let mut composition_mode_changed = false; use egui::Color32; @@ -418,6 +429,7 @@ pub fn draw_legend_panel(ctx: &egui::Context, settings: &mut UiSettings) -> bool composition_mode_changed } +// Draws level tabs. pub fn draw_level_tabs( ui: &mut egui::Ui, level_count: usize, diff --git a/src/ui/tabs.rs b/src/ui/tabs.rs index 852e0fe..dda8209 100644 --- a/src/ui/tabs.rs +++ b/src/ui/tabs.rs @@ -787,6 +787,7 @@ pub fn draw_add_tab(ui: &mut egui::Ui, settings: &mut UiSettings, result: &mut S } } +// Draws start and end tab. pub fn draw_start_and_end_tab( ui: &mut egui::Ui, settings: &mut UiSettings, @@ -869,6 +870,7 @@ pub fn draw_start_and_end_tab( ui.label("Markers are generated inside rooms. Matching start/end indices are paired as far apart as possible."); } +// Draws monsters and traps tab. pub fn draw_monsters_and_traps_tab( ui: &mut egui::Ui, settings: &mut UiSettings, @@ -932,6 +934,7 @@ pub fn draw_monsters_and_traps_tab( ); } +// Draws usize slider row. pub fn draw_usize_slider_row( ui: &mut egui::Ui, result: &mut SidePanelResult, diff --git a/src/ui/widgets.rs b/src/ui/widgets.rs index b977ea1..6dcc95a 100644 --- a/src/ui/widgets.rs +++ b/src/ui/widgets.rs @@ -218,6 +218,7 @@ pub fn draw_dotted_line(painter: &egui::Painter, from: egui::Pos2, to: egui::Pos } } +// Draws dash dot line. pub fn draw_dash_dot_line( painter: &egui::Painter, from: egui::Pos2, @@ -249,6 +250,7 @@ pub fn draw_dash_dot_line( } } +// Draws dash dot dot line. pub fn draw_dash_dot_dot_line( painter: &egui::Painter, from: egui::Pos2,