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,
|
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 {
|
2026-03-19 13:49:42 -05:00
|
|
|
// 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 {
|
2026-03-19 13:49:42 -05:00
|
|
|
// Default export format is PNG.
|
2026-03-06 11:42:20 -06:00
|
|
|
fn default() -> Self {
|
|
|
|
|
Self::Png
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ExportFormat {
|
2026-03-19 13:49:42 -05:00
|
|
|
// 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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 13:49:42 -05: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
|
|
|
}
|
|
|
|
|
}
|
2026-03-06 14:06:40 -06:00
|
|
|
|
2026-03-19 13:49:42 -05:00
|
|
|
// Report whether this export format supports a raster resolution.
|
2026-03-06 14:42:08 -06:00
|
|
|
pub fn supports_resolution(self) -> bool {
|
2026-03-06 14:06:40 -06:00
|
|
|
!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 {
|
2026-03-19 13:49:42 -05:00
|
|
|
// Default mask format is PNG.
|
2026-03-06 14:42:08 -06:00
|
|
|
fn default() -> Self {
|
|
|
|
|
Self::Png
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MaskFormat {
|
2026-03-19 13:49:42 -05:00
|
|
|
// 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",
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 13:49:42 -05:00
|
|
|
// 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-06 09:42:57 -06:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
|
#[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,
|
2026-03-12 08:25:37 -05:00
|
|
|
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,
|
2026-03-23 11:46:52 -05:00
|
|
|
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,
|
|
|
|
|
pub allow_middle_corridor_doors: bool,
|
2026-03-06 11:16:17 -06:00
|
|
|
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,
|
2026-03-06 14:06:40 -06:00
|
|
|
pub export_width: u32,
|
|
|
|
|
pub export_height: u32,
|
|
|
|
|
pub allow_export_aspect_change: bool,
|
2026-03-12 08:50:32 -05:00
|
|
|
pub export_show_grid: bool,
|
2026-03-12 09:58:08 -05:00
|
|
|
pub add_tool: AddTool,
|
2026-03-06 09:24:24 -06:00
|
|
|
active_tab: Tab,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for UiSettings {
|
2026-03-19 13:49:42 -05:00
|
|
|
// 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,
|
2026-03-12 08:25:37 -05:00
|
|
|
min_corridor_width: 1,
|
|
|
|
|
max_corridor_width: 2,
|
2026-03-06 09:24:24 -06:00
|
|
|
corridor_randomness: 0,
|
|
|
|
|
dead_end_rooms_percent: 0,
|
2026-03-23 11:46:52 -05:00
|
|
|
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,
|
|
|
|
|
allow_middle_corridor_doors: false,
|
2026-03-06 11:16:17 -06:00
|
|
|
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,
|
2026-03-06 14:06:40 -06:00
|
|
|
export_width: 1920,
|
|
|
|
|
export_height: 1080,
|
|
|
|
|
allow_export_aspect_change: false,
|
2026-03-12 08:50:32 -05:00
|
|
|
export_show_grid: true,
|
2026-03-12 09:58:08 -05:00
|
|
|
add_tool: AddTool::None,
|
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,
|
2026-03-12 11:36:36 -05:00
|
|
|
Door,
|
|
|
|
|
LockedDoor,
|
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
|
|
|
}
|
|
|
|
|
|
2026-03-12 08:59:28 -05:00
|
|
|
pub fn draw_side_panel(
|
|
|
|
|
ctx: &egui::Context,
|
|
|
|
|
settings: &mut UiSettings,
|
|
|
|
|
export_in_progress: bool,
|
|
|
|
|
) -> SidePanelResult {
|
2026-03-19 13:49:42 -05:00
|
|
|
// 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;
|
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;
|
|
|
|
|
}
|
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 {
|
2026-03-12 08:59:28 -05:00
|
|
|
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),
|
2026-03-12 09:58:08 -05:00
|
|
|
Tab::Add => draw_add_tab(ui, settings),
|
2026-03-06 09:24:24 -06:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-19 13:49:42 -05:00
|
|
|
// Render the Generate tab controls.
|
2026-03-12 08:59:28 -05:00
|
|
|
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");
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-12 08:50:32 -05:00
|
|
|
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() {
|
2026-03-06 14:06:40 -06:00
|
|
|
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))
|
2026-03-06 14:06:40 -06:00
|
|
|
.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;
|
|
|
|
|
}
|
2026-03-12 08:59:28 -05:00
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2026-03-19 13:49:42 -05: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();
|
2026-03-23 11:46:52 -05:00
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
|
2026-03-12 08:25:37 -05:00
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
ui.add_space(8.0);
|
|
|
|
|
result.settings_changed |= ui
|
|
|
|
|
.checkbox(
|
|
|
|
|
&mut settings.allow_middle_corridor_doors,
|
|
|
|
|
"Allow Middle Corridor Doors",
|
|
|
|
|
)
|
|
|
|
|
.changed();
|
2026-03-06 09:24:24 -06:00
|
|
|
}
|
2026-03-12 09:58:08 -05:00
|
|
|
|
2026-03-19 13:49:42 -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-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-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."),
|
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-12 09:58:08 -05:00
|
|
|
AddTool::None => ui.label("Select a tool to add rooms or corridors."),
|
|
|
|
|
};
|
|
|
|
|
}
|