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-04-14 11:03:58 -05:00
|
|
|
StartAndEnd,
|
2026-04-20 09:59:25 -05:00
|
|
|
MonstersAndTraps,
|
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-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,
|
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,
|
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,
|
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-04-20 14:04:59 -05:00
|
|
|
pub last_export_path: Option<String>,
|
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,
|
2026-04-14 11:03:58 -05:00
|
|
|
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-04-20 09:59:25 -05:00
|
|
|
pub trap_frequency_percent: usize,
|
|
|
|
|
pub min_traps_per_area: usize,
|
|
|
|
|
pub max_traps_per_area: usize,
|
|
|
|
|
pub monster_frequency_percent: usize,
|
|
|
|
|
pub min_monsters_per_area: usize,
|
|
|
|
|
pub max_monsters_per_area: usize,
|
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,
|
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,
|
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-04-20 14:04:59 -05:00
|
|
|
last_export_path: None,
|
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(),
|
2026-04-14 11:03:58 -05:00
|
|
|
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-04-20 09:59:25 -05:00
|
|
|
trap_frequency_percent: 20,
|
|
|
|
|
min_traps_per_area: 1,
|
|
|
|
|
max_traps_per_area: 3,
|
|
|
|
|
monster_frequency_percent: 15,
|
|
|
|
|
min_monsters_per_area: 1,
|
|
|
|
|
max_monsters_per_area: 2,
|
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-04-07 11:28:34 -05:00
|
|
|
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-04-20 09:59:25 -05:00
|
|
|
TrapMarker,
|
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-04-20 10:23:49 -05:00
|
|
|
pub save_clicked: bool,
|
|
|
|
|
pub load_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;
|
|
|
|
|
|
|
|
|
|
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-04-20 09:59:25 -05:00
|
|
|
if ui
|
|
|
|
|
.selectable_label(settings.active_tab == Tab::StartAndEnd, "Start & End")
|
|
|
|
|
.clicked()
|
|
|
|
|
{
|
2026-04-14 11:03:58 -05:00
|
|
|
settings.active_tab = Tab::StartAndEnd;
|
|
|
|
|
}
|
2026-04-20 09:59:25 -05:00
|
|
|
if ui
|
|
|
|
|
.selectable_label(
|
|
|
|
|
settings.active_tab == Tab::MonstersAndTraps,
|
|
|
|
|
"Monsters/Traps",
|
|
|
|
|
)
|
|
|
|
|
.clicked()
|
|
|
|
|
{
|
|
|
|
|
settings.active_tab = Tab::MonstersAndTraps;
|
|
|
|
|
}
|
|
|
|
|
if ui
|
|
|
|
|
.selectable_label(settings.active_tab == Tab::Add, "Add")
|
|
|
|
|
.clicked()
|
|
|
|
|
{
|
2026-03-12 09:58:08 -05:00
|
|
|
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-04-14 11:03:58 -05:00
|
|
|
Tab::StartAndEnd => draw_start_and_end_tab(ui, settings, &mut result),
|
2026-04-20 09:59:25 -05:00
|
|
|
Tab::MonstersAndTraps => draw_monsters_and_traps_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
|
|
|
|
2026-04-20 10:55:31 -05:00
|
|
|
ui.add_space(12.0);
|
|
|
|
|
ui.separator();
|
2026-04-20 10:23:49 -05:00
|
|
|
ui.add_space(8.0);
|
2026-04-20 10:55:31 -05:00
|
|
|
ui.label(RichText::new("Dungeon Files").strong());
|
|
|
|
|
ui.add_space(8.0);
|
|
|
|
|
|
2026-04-20 10:23:49 -05:00
|
|
|
ui.horizontal(|ui| {
|
|
|
|
|
if ui.button("Save State").clicked() {
|
|
|
|
|
result.save_clicked = true;
|
|
|
|
|
}
|
|
|
|
|
if ui.button("Load State").clicked() {
|
|
|
|
|
result.load_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);
|
2026-04-20 14:33:27 -05:00
|
|
|
let export_button = ui.add_enabled(!export_in_progress, egui::Button::new("Export Image"));
|
|
|
|
|
if export_button.clicked() {
|
2026-03-06 11:42:20 -06:00
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
|
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
|
|
|
|
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-24 09:27:53 -05:00
|
|
|
});
|
|
|
|
|
ui.add_space(4.0);
|
|
|
|
|
ui.horizontal(|ui| {
|
2026-04-07 11:28:34 -05:00
|
|
|
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");
|
2026-04-14 11:03:58 -05:00
|
|
|
ui.selectable_value(&mut settings.add_tool, AddTool::StartMarker, "Place Start");
|
|
|
|
|
ui.selectable_value(&mut settings.add_tool, AddTool::EndMarker, "Place End");
|
2026-04-20 09:59:25 -05:00
|
|
|
ui.selectable_value(&mut settings.add_tool, AddTool::TrapMarker, "Place Trap");
|
2026-03-12 09:58:08 -05:00
|
|
|
});
|
2026-04-20 13:57:46 -05:00
|
|
|
ui.add_space(4.0);
|
|
|
|
|
ui.label("Left click to place, Right click/Escape to cancel");
|
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-04-07 11:28:34 -05:00
|
|
|
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
|
|
|
|
|
}
|
2026-04-14 11:03:58 -05:00
|
|
|
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-04-20 09:59:25 -05:00
|
|
|
AddTool::TrapMarker => ui.label("Click the grid to place a trap 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
|
|
|
|
2026-04-14 11:03:58 -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);
|
2026-04-14 11:47:31 -05:00
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Min Start Marker Size",
|
|
|
|
|
&mut settings.min_start_marker_size,
|
|
|
|
|
1..=10,
|
|
|
|
|
1..=10,
|
|
|
|
|
);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Max Start Marker Size",
|
|
|
|
|
&mut settings.max_start_marker_size,
|
|
|
|
|
1..=10,
|
|
|
|
|
1..=10,
|
|
|
|
|
);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Min Start Marker Count",
|
|
|
|
|
&mut settings.min_start_marker_count,
|
|
|
|
|
1..=20,
|
|
|
|
|
1..=100,
|
|
|
|
|
);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Max Start Marker Count",
|
|
|
|
|
&mut settings.max_start_marker_count,
|
|
|
|
|
1..=20,
|
|
|
|
|
1..=100,
|
|
|
|
|
);
|
2026-04-14 10:31:26 -05:00
|
|
|
|
2026-04-14 11:03:58 -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);
|
2026-04-14 11:47:31 -05:00
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Min End Marker Size",
|
|
|
|
|
&mut settings.min_end_marker_size,
|
|
|
|
|
1..=10,
|
|
|
|
|
1..=10,
|
|
|
|
|
);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Max End Marker Size",
|
|
|
|
|
&mut settings.max_end_marker_size,
|
|
|
|
|
1..=10,
|
|
|
|
|
1..=10,
|
|
|
|
|
);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Min End Marker Count",
|
|
|
|
|
&mut settings.min_end_marker_count,
|
|
|
|
|
1..=20,
|
|
|
|
|
1..=100,
|
|
|
|
|
);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Max End Marker Count",
|
|
|
|
|
&mut settings.max_end_marker_count,
|
|
|
|
|
1..=20,
|
|
|
|
|
1..=100,
|
|
|
|
|
);
|
2026-04-14 10:31:26 -05:00
|
|
|
|
|
|
|
|
ui.add_space(8.0);
|
2026-04-14 11:03:58 -05:00
|
|
|
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
|
|
|
}
|
2026-04-14 11:47:31 -05:00
|
|
|
|
2026-04-20 09:59:25 -05:00
|
|
|
fn draw_monsters_and_traps_tab(
|
|
|
|
|
ui: &mut egui::Ui,
|
|
|
|
|
settings: &mut UiSettings,
|
|
|
|
|
result: &mut SidePanelResult,
|
|
|
|
|
) {
|
|
|
|
|
ui.label(RichText::new("Trap Settings").strong());
|
|
|
|
|
ui.add_space(8.0);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Trap Frequency (%)",
|
|
|
|
|
&mut settings.trap_frequency_percent,
|
|
|
|
|
0..=100,
|
|
|
|
|
0..=100,
|
|
|
|
|
);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Min Traps Per Room/Corridor",
|
|
|
|
|
&mut settings.min_traps_per_area,
|
|
|
|
|
0..=20,
|
|
|
|
|
0..=100,
|
|
|
|
|
);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Max Traps Per Room/Corridor",
|
|
|
|
|
&mut settings.max_traps_per_area,
|
|
|
|
|
0..=20,
|
|
|
|
|
0..=100,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
ui.add_space(12.0);
|
|
|
|
|
ui.separator();
|
|
|
|
|
ui.add_space(8.0);
|
|
|
|
|
ui.label(RichText::new("Monster Settings").strong());
|
|
|
|
|
ui.add_space(8.0);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Monster Frequency (%)",
|
|
|
|
|
&mut settings.monster_frequency_percent,
|
|
|
|
|
0..=100,
|
|
|
|
|
0..=100,
|
|
|
|
|
);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Min Monsters Per Room/Corridor",
|
|
|
|
|
&mut settings.min_monsters_per_area,
|
|
|
|
|
0..=20,
|
|
|
|
|
0..=100,
|
|
|
|
|
);
|
|
|
|
|
draw_usize_slider_row(
|
|
|
|
|
ui,
|
|
|
|
|
result,
|
|
|
|
|
"Max Monsters Per Room/Corridor",
|
|
|
|
|
&mut settings.max_monsters_per_area,
|
|
|
|
|
0..=20,
|
|
|
|
|
0..=100,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-14 11:47:31 -05:00
|
|
|
fn draw_usize_slider_row(
|
|
|
|
|
ui: &mut egui::Ui,
|
|
|
|
|
result: &mut SidePanelResult,
|
|
|
|
|
label: &str,
|
|
|
|
|
value: &mut usize,
|
|
|
|
|
slider_range: std::ops::RangeInclusive<usize>,
|
|
|
|
|
drag_range: std::ops::RangeInclusive<usize>,
|
|
|
|
|
) {
|
|
|
|
|
ui.label(label);
|
|
|
|
|
ui.horizontal(|ui| {
|
|
|
|
|
result.settings_changed |= ui
|
|
|
|
|
.add(egui::Slider::new(value, slider_range).show_value(false))
|
|
|
|
|
.changed();
|
|
|
|
|
result.settings_changed |= ui
|
|
|
|
|
.add(egui::DragValue::new(value).speed(1.0).range(drag_range))
|
|
|
|
|
.changed();
|
|
|
|
|
});
|
|
|
|
|
ui.add_space(6.0);
|
|
|
|
|
}
|