Files
desktop_dungeon_generator/src/ui.rs
T

362 lines
10 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,
}
2026-03-06 09:42:57 -06:00
impl Default for Tab {
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,
}
impl Default for ExportFormat {
fn default() -> Self {
Self::Png
}
}
impl ExportFormat {
pub fn extension(self) -> &'static str {
match self {
ExportFormat::Png => "png",
ExportFormat::Jpeg => "jpeg",
ExportFormat::Webp => "webp",
ExportFormat::Svg => "svg",
}
}
pub fn label(self) -> &'static str {
match self {
ExportFormat::Png => ".png",
ExportFormat::Jpeg => ".jpeg",
ExportFormat::Webp => ".webp",
ExportFormat::Svg => ".svg",
}
}
}
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,
pub corridor_randomness: usize,
pub dead_end_rooms_percent: usize,
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,
pub colorblind_mode: bool,
2026-03-06 11:42:20 -06:00
pub export_format: ExportFormat,
2026-03-06 09:24:24 -06:00
active_tab: Tab,
}
impl Default for UiSettings {
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,
corridor_randomness: 0,
dead_end_rooms_percent: 0,
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,
colorblind_mode: false,
2026-03-06 11:42:20 -06:00
export_format: ExportFormat::Png,
2026-03-06 09:24:24 -06:00
active_tab: Tab::Generate,
}
}
}
#[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-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) -> SidePanelResult {
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;
}
});
ui.separator();
match settings.active_tab {
Tab::Generate => draw_generate_tab(ui, settings, &mut result),
Tab::Layout => draw_layout_tab(ui, settings, &mut result),
}
});
result
}
fn draw_generate_tab(ui: &mut egui::Ui, settings: &mut UiSettings, result: &mut SidePanelResult) {
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);
if ui.button("Reset").clicked() {
result.reset_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");
});
});
ui.add_space(6.0);
if ui.button("Export Image").clicked() {
result.export_clicked = true;
}
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();
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("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
}