Files
desktop_dungeon_generator/src/ui.rs
T

906 lines
29 KiB
Rust
Raw Normal View History

2026-03-06 09:40:22 -06:00
use crate::seed;
2026-03-06 09:24:24 -06:00
use eframe::egui;
use egui::RichText;
2026-03-06 09:42:57 -06:00
use serde::{Deserialize, Serialize};
2026-03-06 09:24:24 -06:00
2026-03-06 09:42:57 -06:00
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
2026-03-06 09:24:24 -06:00
enum Tab {
Generate,
Layout,
StartAndEnd,
2026-03-12 09:58:08 -05:00
Add,
2026-03-06 09:24:24 -06:00
}
2026-03-06 09:42:57 -06:00
impl Default for Tab {
// Start with the Generate tab selected.
2026-03-06 09:42:57 -06:00
fn default() -> Self {
Self::Generate
}
}
2026-03-06 11:42:20 -06:00
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ExportFormat {
Png,
Jpeg,
Webp,
Svg,
2026-03-06 14:42:08 -06:00
Folder,
2026-03-06 11:42:20 -06:00
}
impl Default for ExportFormat {
// Default export format is PNG.
2026-03-06 11:42:20 -06:00
fn default() -> Self {
Self::Png
}
}
impl ExportFormat {
// Return the file extension for this export format.
2026-03-06 11:42:20 -06:00
pub fn extension(self) -> &'static str {
match self {
ExportFormat::Png => "png",
ExportFormat::Jpeg => "jpeg",
ExportFormat::Webp => "webp",
ExportFormat::Svg => "svg",
2026-03-06 14:42:08 -06:00
ExportFormat::Folder => "folder",
2026-03-06 11:42:20 -06:00
}
}
// Return the UI label for this export format.
2026-03-06 11:42:20 -06:00
pub fn label(self) -> &'static str {
match self {
ExportFormat::Png => ".png",
ExportFormat::Jpeg => ".jpeg",
ExportFormat::Webp => ".webp",
ExportFormat::Svg => ".svg",
2026-03-06 14:42:08 -06:00
ExportFormat::Folder => "Folder (Composite)",
2026-03-06 11:42:20 -06:00
}
}
// Report whether this export format supports a raster resolution.
2026-03-06 14:42:08 -06:00
pub fn supports_resolution(self) -> bool {
!matches!(self, ExportFormat::Svg)
}
2026-03-06 11:42:20 -06:00
}
2026-03-06 14:42:08 -06:00
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum MaskFormat {
Png,
Jpeg,
Webp,
}
impl Default for MaskFormat {
// Default mask format is PNG.
2026-03-06 14:42:08 -06:00
fn default() -> Self {
Self::Png
}
}
impl MaskFormat {
// Return the file extension for this mask format.
2026-03-06 14:42:08 -06:00
pub fn extension(self) -> &'static str {
match self {
MaskFormat::Png => "png",
MaskFormat::Jpeg => "jpeg",
MaskFormat::Webp => "webp",
}
}
// Return the UI label for this mask format.
2026-03-06 14:42:08 -06:00
pub fn label(self) -> &'static str {
match self {
MaskFormat::Png => ".png",
MaskFormat::Jpeg => ".jpeg",
MaskFormat::Webp => ".webp",
}
}
}
2026-03-24 09:06:48 -05:00
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
2026-03-06 09:42:57 -06:00
#[serde(default)]
2026-03-06 09:24:24 -06:00
pub struct UiSettings {
2026-03-06 09:40:22 -06:00
pub seed: u64,
2026-03-06 09:24:24 -06:00
pub cols: usize,
pub rows: usize,
pub room_count: usize,
pub min_room_size: usize,
pub max_room_size: usize,
pub square_rooms_only: bool,
pub min_corridor_width: usize,
pub max_corridor_width: usize,
2026-03-06 09:24:24 -06:00
pub corridor_randomness: usize,
pub dead_end_rooms_percent: usize,
pub pack_rooms_without_corridors: bool,
2026-03-06 10:53:46 -06:00
pub door_frequency_percent: usize,
pub room_hallway_door_percent: usize,
pub locked_door_percent: usize,
2026-03-23 12:43:33 -05:00
pub secret_door_percent: usize,
2026-03-06 10:53:46 -06:00
pub allow_middle_corridor_doors: bool,
2026-03-23 12:22:03 -05:00
pub windows_enabled: bool,
pub min_window_width: usize,
pub max_window_width: usize,
pub window_frequency_percent: usize,
pub room_hallway_window_percent: usize,
pub allow_internal_windows: bool,
pub colorblind_mode: bool,
2026-03-06 11:42:20 -06:00
pub export_format: ExportFormat,
2026-03-06 14:42:08 -06:00
pub mask_format: MaskFormat,
pub export_width: u32,
pub export_height: u32,
pub allow_export_aspect_change: bool,
pub export_show_grid: bool,
2026-03-12 09:58:08 -05:00
pub add_tool: AddTool,
2026-03-24 09:25:44 -05:00
pub add_text_value: String,
pub min_start_marker_size: usize,
pub max_start_marker_size: usize,
pub min_end_marker_size: usize,
pub max_end_marker_size: usize,
pub min_start_marker_count: usize,
pub max_start_marker_count: usize,
pub min_end_marker_count: usize,
pub max_end_marker_count: usize,
2026-03-06 09:24:24 -06:00
active_tab: Tab,
}
impl Default for UiSettings {
// Provide initial UI settings for a fresh session.
2026-03-06 09:24:24 -06:00
fn default() -> Self {
Self {
2026-03-06 09:40:22 -06:00
seed: 1,
2026-03-06 09:24:24 -06:00
cols: 24,
rows: 18,
room_count: 8,
min_room_size: 2,
max_room_size: 6,
square_rooms_only: false,
min_corridor_width: 1,
max_corridor_width: 2,
2026-03-06 09:24:24 -06:00
corridor_randomness: 0,
dead_end_rooms_percent: 0,
pack_rooms_without_corridors: false,
2026-03-06 10:53:46 -06:00
door_frequency_percent: 30,
room_hallway_door_percent: 70,
locked_door_percent: 25,
2026-03-23 12:43:33 -05:00
secret_door_percent: 10,
2026-03-06 10:53:46 -06:00
allow_middle_corridor_doors: false,
2026-03-23 12:22:03 -05:00
windows_enabled: false,
min_window_width: 1,
max_window_width: 2,
window_frequency_percent: 30,
room_hallway_window_percent: 40,
allow_internal_windows: false,
colorblind_mode: false,
2026-03-06 11:42:20 -06:00
export_format: ExportFormat::Png,
2026-03-06 14:42:08 -06:00
mask_format: MaskFormat::Png,
export_width: 1920,
export_height: 1080,
allow_export_aspect_change: false,
export_show_grid: true,
2026-03-12 09:58:08 -05:00
add_tool: AddTool::None,
2026-03-24 09:25:44 -05:00
add_text_value: "Text".to_string(),
min_start_marker_size: 1,
max_start_marker_size: 1,
min_end_marker_size: 1,
max_end_marker_size: 1,
min_start_marker_count: 1,
max_start_marker_count: 1,
min_end_marker_count: 1,
max_end_marker_count: 1,
2026-03-06 09:24:24 -06:00
active_tab: Tab::Generate,
}
}
}
2026-03-12 09:58:08 -05:00
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum AddTool {
None,
Room,
Corridor,
Archway,
2026-03-12 11:36:36 -05:00
Door,
LockedDoor,
2026-03-23 12:43:33 -05:00
SecretDoor,
2026-03-24 09:25:44 -05:00
Text,
2026-04-14 10:31:26 -05:00
StartMarker,
EndMarker,
2026-03-12 09:58:08 -05:00
}
2026-03-06 09:24:24 -06:00
#[derive(Debug, Clone, Copy, Default)]
pub struct SidePanelResult {
pub settings_changed: bool,
2026-03-06 09:56:26 -06:00
pub reset_clicked: bool,
2026-03-23 11:49:24 -05:00
pub clear_clicked: bool,
2026-03-06 11:42:20 -06:00
pub export_clicked: bool,
2026-03-06 09:24:24 -06:00
}
pub fn draw_side_panel(
ctx: &egui::Context,
settings: &mut UiSettings,
export_in_progress: bool,
) -> SidePanelResult {
// Render the left side panel and return user interaction results.
2026-03-06 09:24:24 -06:00
let mut result = SidePanelResult::default();
egui::SidePanel::left("options_panel")
.resizable(true)
.min_width(180.0)
.default_width(280.0)
.show_separator_line(true)
.show(ctx, |ui| {
ui.horizontal(|ui| {
let is_generate = settings.active_tab == Tab::Generate;
let is_layout = settings.active_tab == Tab::Layout;
let is_start_and_end = settings.active_tab == Tab::StartAndEnd;
2026-03-12 09:58:08 -05:00
let is_add = settings.active_tab == Tab::Add;
2026-03-06 09:24:24 -06:00
if ui.selectable_label(is_generate, "Generate").clicked() {
settings.active_tab = Tab::Generate;
}
if ui.selectable_label(is_layout, "Layout").clicked() {
settings.active_tab = Tab::Layout;
}
if ui.selectable_label(is_start_and_end, "Start & End").clicked() {
settings.active_tab = Tab::StartAndEnd;
}
2026-03-12 09:58:08 -05:00
if ui.selectable_label(is_add, "Add").clicked() {
settings.active_tab = Tab::Add;
}
2026-03-06 09:24:24 -06:00
});
ui.separator();
match settings.active_tab {
Tab::Generate => draw_generate_tab(ui, settings, &mut result, export_in_progress),
2026-03-06 09:24:24 -06:00
Tab::Layout => draw_layout_tab(ui, settings, &mut result),
Tab::StartAndEnd => draw_start_and_end_tab(ui, settings, &mut result),
2026-03-12 09:58:08 -05:00
Tab::Add => draw_add_tab(ui, settings),
2026-03-06 09:24:24 -06:00
}
});
result
}
// Render the Generate tab controls.
fn draw_generate_tab(
ui: &mut egui::Ui,
settings: &mut UiSettings,
result: &mut SidePanelResult,
export_in_progress: bool,
) {
2026-03-06 09:24:24 -06:00
ui.label(RichText::new("Grid Settings").strong());
ui.add_space(8.0);
ui.label("Columns");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.cols, 6..=100).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.cols)
.speed(1.0)
.range(2..=500),
)
.changed();
});
ui.add_space(8.0);
ui.label("Rows");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.rows, 6..=100).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.rows)
.speed(1.0)
.range(2..=500),
)
.changed();
});
ui.add_space(12.0);
2026-03-06 09:40:22 -06:00
ui.separator();
ui.add_space(8.0);
ui.label(RichText::new("Seed Settings").strong());
2026-03-06 09:24:24 -06:00
ui.add_space(8.0);
2026-03-06 09:40:22 -06:00
ui.label("Master Seed");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::DragValue::new(&mut settings.seed).speed(1.0))
.changed();
if ui.button("Random").clicked() {
settings.seed = seed::random_seed();
result.settings_changed = true;
}
});
2026-03-06 09:56:26 -06:00
ui.add_space(8.0);
2026-03-23 11:49:24 -05:00
ui.horizontal(|ui| {
if ui.button("Reset").clicked() {
result.reset_clicked = true;
}
if ui.button("Clear").clicked() {
result.clear_clicked = true;
}
});
2026-03-06 11:42:20 -06:00
ui.add_space(12.0);
ui.separator();
ui.add_space(8.0);
ui.label(RichText::new("Export").strong());
ui.add_space(8.0);
ui.horizontal(|ui| {
ui.label("Format");
egui::ComboBox::from_id_salt("export_format")
.selected_text(settings.export_format.label())
.show_ui(ui, |ui| {
ui.selectable_value(&mut settings.export_format, ExportFormat::Png, ".png");
ui.selectable_value(&mut settings.export_format, ExportFormat::Jpeg, ".jpeg");
ui.selectable_value(&mut settings.export_format, ExportFormat::Webp, ".webp");
ui.selectable_value(&mut settings.export_format, ExportFormat::Svg, ".svg");
2026-03-06 14:42:08 -06:00
ui.selectable_value(
&mut settings.export_format,
ExportFormat::Folder,
"Folder (Composite)",
);
2026-03-06 11:42:20 -06:00
});
});
2026-03-06 14:42:08 -06:00
if settings.export_format == ExportFormat::Folder {
ui.add_space(6.0);
ui.horizontal(|ui| {
ui.label("Mask Format");
egui::ComboBox::from_id_salt("mask_format")
.selected_text(settings.mask_format.label())
.show_ui(ui, |ui| {
ui.selectable_value(&mut settings.mask_format, MaskFormat::Png, ".png");
ui.selectable_value(&mut settings.mask_format, MaskFormat::Jpeg, ".jpeg");
ui.selectable_value(&mut settings.mask_format, MaskFormat::Webp, ".webp");
});
});
}
ui.add_space(6.0);
result.settings_changed |= ui
.checkbox(&mut settings.export_show_grid, "Include Grid In Export")
.changed();
2026-03-06 14:42:08 -06:00
if settings.export_format.supports_resolution() {
ui.add_space(8.0);
ui.checkbox(
&mut settings.allow_export_aspect_change,
"Allow aspect ratio change",
);
let mut width_changed = false;
let mut height_changed = false;
ui.add_space(6.0);
ui.label("Resolution Width");
ui.horizontal(|ui| {
width_changed |= ui
.add(egui::Slider::new(&mut settings.export_width, 1..=10_000).show_value(false))
.changed();
width_changed |= ui
.add(
egui::DragValue::new(&mut settings.export_width)
.speed(1.0)
.range(1..=10_000),
)
.changed();
});
ui.add_space(6.0);
ui.label("Resolution Height");
ui.horizontal(|ui| {
height_changed |= ui
2026-03-06 14:42:08 -06:00
.add(egui::Slider::new(&mut settings.export_height, 1..=10_000).show_value(false))
.changed();
height_changed |= ui
.add(
egui::DragValue::new(&mut settings.export_height)
.speed(1.0)
.range(1..=10_000),
)
.changed();
});
if !settings.allow_export_aspect_change {
let cols = settings.cols.max(1) as f32;
let rows = settings.rows.max(1) as f32;
let ratio = cols / rows;
if width_changed {
let h = ((settings.export_width as f32) / ratio).round() as u32;
settings.export_height = h.clamp(1, 10_000);
} else if height_changed {
let w = ((settings.export_height as f32) * ratio).round() as u32;
settings.export_width = w.clamp(1, 10_000);
}
}
}
2026-03-06 11:42:20 -06:00
ui.add_space(6.0);
if ui.button("Export Image").clicked() {
result.export_clicked = true;
}
if export_in_progress {
ui.add_space(6.0);
ui.add(egui::ProgressBar::new(0.0).animate(true));
}
2026-03-06 09:24:24 -06:00
}
// Render the Layout tab controls.
2026-03-06 09:24:24 -06:00
fn draw_layout_tab(ui: &mut egui::Ui, settings: &mut UiSettings, result: &mut SidePanelResult) {
ui.label(RichText::new("Room Settings").strong());
ui.add_space(8.0);
ui.label("Room Count");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.room_count, 1..=40).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.room_count)
.speed(1.0)
.range(1..=200),
)
.changed();
});
ui.add_space(8.0);
ui.label("Min Room Size");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.min_room_size, 2..=30).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.min_room_size)
.speed(1.0)
.range(2..=200),
)
.changed();
});
ui.add_space(8.0);
ui.label("Max Room Size");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.max_room_size, 2..=30).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.max_room_size)
.speed(1.0)
.range(2..=200),
)
.changed();
});
ui.add_space(8.0);
result.settings_changed |= ui
.checkbox(&mut settings.square_rooms_only, "Square Rooms Only")
.changed();
result.settings_changed |= ui
.checkbox(
&mut settings.pack_rooms_without_corridors,
"Pack Rooms Together (No Corridors)",
)
.changed();
2026-03-06 09:24:24 -06:00
ui.add_space(12.0);
ui.separator();
ui.add_space(8.0);
ui.label(RichText::new("Corridor Settings").strong());
ui.add_space(8.0);
ui.label("Corridor Randomness (%)");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.corridor_randomness, 0..=100).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.corridor_randomness)
.speed(1.0)
.range(0..=100),
)
.changed();
});
ui.add_space(8.0);
ui.label("Min Corridor Width");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.min_corridor_width, 1..=10).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.min_corridor_width)
.speed(1.0)
.range(1..=50),
)
.changed();
});
ui.add_space(8.0);
ui.label("Max Corridor Width");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.max_corridor_width, 1..=10).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.max_corridor_width)
.speed(1.0)
.range(1..=50),
)
.changed();
});
2026-03-06 09:24:24 -06:00
ui.add_space(8.0);
ui.label("Dead-End Rooms (%)");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.dead_end_rooms_percent, 0..=50).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.dead_end_rooms_percent)
.speed(1.0)
.range(0..=50),
)
.changed();
});
2026-03-06 10:53:46 -06:00
ui.add_space(12.0);
ui.separator();
ui.add_space(8.0);
ui.label(RichText::new("Door Settings").strong());
ui.add_space(8.0);
ui.label("Door Frequency (%)");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.door_frequency_percent, 0..=100).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.door_frequency_percent)
.speed(1.0)
.range(0..=100),
)
.changed();
});
ui.add_space(8.0);
ui.label("Room/Hallway Door Chance (%)");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(
egui::Slider::new(&mut settings.room_hallway_door_percent, 0..=100)
.show_value(false),
)
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.room_hallway_door_percent)
.speed(1.0)
.range(0..=100),
)
.changed();
});
ui.add_space(8.0);
ui.label("Locked Door Chance (%)");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.locked_door_percent, 0..=100).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.locked_door_percent)
.speed(1.0)
.range(0..=100),
)
.changed();
});
2026-03-23 12:43:33 -05:00
ui.add_space(8.0);
ui.label("Secret Door Chance (%)");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.secret_door_percent, 0..=100).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.secret_door_percent)
.speed(1.0)
.range(0..=100),
)
.changed();
});
2026-03-06 10:53:46 -06:00
ui.add_space(8.0);
result.settings_changed |= ui
.checkbox(
&mut settings.allow_middle_corridor_doors,
"Allow Middle Corridor Doors",
)
.changed();
2026-03-23 12:22:03 -05:00
ui.add_space(12.0);
ui.separator();
ui.add_space(8.0);
ui.label(RichText::new("Window Settings").strong());
ui.add_space(8.0);
result.settings_changed |= ui
.checkbox(&mut settings.windows_enabled, "Enable Windows")
.changed();
if settings.windows_enabled {
ui.add_space(8.0);
ui.label("Min Window Width");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.min_window_width, 1..=5).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.min_window_width)
.speed(1.0)
.range(1..=5),
)
.changed();
});
ui.add_space(8.0);
ui.label("Max Window Width");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.max_window_width, 1..=5).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.max_window_width)
.speed(1.0)
.range(1..=5),
)
.changed();
});
ui.add_space(8.0);
ui.label("Window Frequency (%)");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(
egui::Slider::new(&mut settings.window_frequency_percent, 0..=100)
.show_value(false),
)
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.window_frequency_percent)
.speed(1.0)
.range(0..=100),
)
.changed();
});
ui.add_space(8.0);
ui.label("Internal Window Chance (%)");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(
egui::Slider::new(&mut settings.room_hallway_window_percent, 0..=100)
.show_value(false),
)
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.room_hallway_window_percent)
.speed(1.0)
.range(0..=100),
)
.changed();
});
ui.add_space(8.0);
result.settings_changed |= ui
.checkbox(
&mut settings.allow_internal_windows,
"Allow Internal Windows",
)
.changed();
}
2026-03-06 09:24:24 -06:00
}
2026-03-12 09:58:08 -05:00
// Render the Add tab controls.
2026-03-12 09:58:08 -05:00
fn draw_add_tab(ui: &mut egui::Ui, settings: &mut UiSettings) {
ui.label(RichText::new("Add Tools").strong());
ui.add_space(8.0);
ui.horizontal(|ui| {
ui.selectable_value(&mut settings.add_tool, AddTool::Room, "Add Room");
ui.selectable_value(&mut settings.add_tool, AddTool::Corridor, "Add Corridor");
2026-03-24 09:27:53 -05:00
});
ui.add_space(4.0);
ui.horizontal(|ui| {
ui.selectable_value(&mut settings.add_tool, AddTool::Archway, "Add Archway");
2026-03-12 11:36:36 -05:00
ui.selectable_value(&mut settings.add_tool, AddTool::Door, "Add Door");
ui.selectable_value(
&mut settings.add_tool,
AddTool::LockedDoor,
"Add Locked Door",
);
2026-03-23 12:43:33 -05:00
ui.selectable_value(
&mut settings.add_tool,
AddTool::SecretDoor,
"Add Secret Door",
);
2026-03-24 09:27:53 -05:00
});
ui.add_space(4.0);
ui.horizontal(|ui| {
2026-03-24 09:25:44 -05:00
ui.selectable_value(&mut settings.add_tool, AddTool::Text, "Add Text");
ui.selectable_value(&mut settings.add_tool, AddTool::StartMarker, "Place Start");
ui.selectable_value(&mut settings.add_tool, AddTool::EndMarker, "Place End");
2026-03-12 09:58:08 -05:00
});
ui.add_space(6.0);
match settings.add_tool {
AddTool::Room => ui.label("Click to place a room at the grid cell."),
AddTool::Corridor => ui.label("Click-drag to place a corridor between two cells."),
AddTool::Archway => ui.label("Click a valid room or corridor edge to place an archway."),
2026-03-12 11:36:36 -05:00
AddTool::Door => ui.label("Click a room/corridor edge to place a door."),
AddTool::LockedDoor => ui.label("Click a room/corridor edge to place a locked door."),
2026-03-23 12:43:33 -05:00
AddTool::SecretDoor => ui.label("Click a room/corridor edge to place a secret door."),
2026-03-24 09:25:44 -05:00
AddTool::Text => {
ui.label("Enter the label text, then click a grid cell to place it.");
ui.add_space(6.0);
ui.label("Text");
let response = ui.text_edit_singleline(&mut settings.add_text_value);
ui.add_space(4.0);
ui.label("Note: Left click on the canvas to place the text.");
response
}
AddTool::StartMarker => ui.label("Click the grid to place the start marker."),
AddTool::EndMarker => ui.label("Click the grid to place the end marker."),
2026-03-12 09:58:08 -05:00
AddTool::None => ui.label("Select a tool to add rooms or corridors."),
};
}
2026-04-14 10:31:26 -05:00
fn draw_start_and_end_tab(
ui: &mut egui::Ui,
settings: &mut UiSettings,
result: &mut SidePanelResult,
) {
ui.label(RichText::new("Start Markers").strong());
2026-04-14 10:31:26 -05:00
ui.add_space(8.0);
ui.label("Min Start Marker Size");
2026-04-14 10:31:26 -05:00
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.min_start_marker_size, 1..=10).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.min_start_marker_size)
2026-04-14 10:31:26 -05:00
.speed(1.0)
.range(1..=10),
)
.changed();
2026-04-14 10:31:26 -05:00
});
ui.add_space(6.0);
ui.label("Max Start Marker Size");
2026-04-14 10:31:26 -05:00
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.max_start_marker_size, 1..=10).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.max_start_marker_size)
2026-04-14 10:31:26 -05:00
.speed(1.0)
.range(1..=10),
)
.changed();
});
ui.add_space(6.0);
ui.label("Min Start Marker Count");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.min_start_marker_count, 1..=20).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.min_start_marker_count)
.speed(1.0)
.range(1..=100),
)
.changed();
});
ui.add_space(6.0);
ui.label("Max Start Marker Count");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.max_start_marker_count, 1..=20).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.max_start_marker_count)
.speed(1.0)
.range(1..=100),
)
.changed();
2026-04-14 10:31:26 -05:00
});
ui.add_space(12.0);
ui.separator();
ui.add_space(8.0);
ui.label(RichText::new("End Markers").strong());
ui.add_space(8.0);
ui.label("Min End Marker Size");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.min_end_marker_size, 1..=10).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.min_end_marker_size)
.speed(1.0)
.range(1..=10),
)
.changed();
});
ui.add_space(6.0);
ui.label("Max End Marker Size");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.max_end_marker_size, 1..=10).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.max_end_marker_size)
.speed(1.0)
.range(1..=10),
)
.changed();
});
ui.add_space(6.0);
ui.label("Min End Marker Count");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.min_end_marker_count, 1..=20).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.min_end_marker_count)
.speed(1.0)
.range(1..=100),
)
.changed();
});
ui.add_space(6.0);
ui.label("Max End Marker Count");
ui.horizontal(|ui| {
result.settings_changed |= ui
.add(egui::Slider::new(&mut settings.max_end_marker_count, 1..=20).show_value(false))
.changed();
result.settings_changed |= ui
.add(
egui::DragValue::new(&mut settings.max_end_marker_count)
.speed(1.0)
.range(1..=100),
)
.changed();
});
2026-04-14 10:31:26 -05:00
ui.add_space(8.0);
ui.label("Markers are generated inside rooms. Matching start/end indices are paired as far apart as possible.");
2026-04-14 10:31:26 -05:00
}