made settings persistant

This commit is contained in:
grimsace
2026-03-06 09:42:57 -06:00
parent 83695f5d1d
commit 70eb567cf4
5 changed files with 62 additions and 4 deletions
+3
View File
@@ -5,3 +5,6 @@ edition = "2024"
[dependencies] [dependencies]
eframe = "0.31" eframe = "0.31"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
dirs = "6"
+3 -1
View File
@@ -21,7 +21,6 @@ A Rust desktop app for generating simple tabletop dungeon layouts.
- Generate control: - Generate control:
- Master seed input (`u64`) - Master seed input (`u64`)
- `Random` seed button - `Random` seed button
- `Generate New Layout` button generates using the current seed
## Generation Behavior ## Generation Behavior
@@ -56,3 +55,6 @@ cargo run
- Rendering is vector-based in-app (`egui` painter), so zooming/scaling the preview remains crisp. - Rendering is vector-based in-app (`egui` painter), so zooming/scaling the preview remains crisp.
- Room and corridor vectors are stored separately to support future export workflows (for example, SVG export). - Room and corridor vectors are stored separately to support future export workflows (for example, SVG export).
- Settings are persisted on exit and restored on startup from:
- Windows: `%LOCALAPPDATA%/desktop_dungeon_generator/settings.json`
- Linux: `~/.local/share/desktop_dungeon_generator/settings.json` (or distro-equivalent local data dir)
+10 -1
View File
@@ -1,4 +1,5 @@
mod layout; mod layout;
mod persistence;
mod seed; mod seed;
mod ui; mod ui;
@@ -26,7 +27,7 @@ struct DungeonApp {
impl Default for DungeonApp { impl Default for DungeonApp {
fn default() -> Self { fn default() -> Self {
let settings = UiSettings::default(); let settings = persistence::load_settings().unwrap_or_default();
let layout = generate_layout( let layout = generate_layout(
settings.cols, settings.cols,
settings.rows, settings.rows,
@@ -43,6 +44,14 @@ impl Default for DungeonApp {
} }
} }
impl Drop for DungeonApp {
fn drop(&mut self) {
if let Err(err) = persistence::save_settings(&self.settings) {
eprintln!("Failed to save settings: {err}");
}
}
}
impl eframe::App for DungeonApp { impl eframe::App for DungeonApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let panel_result = draw_side_panel(ctx, &mut self.settings); let panel_result = draw_side_panel(ctx, &mut self.settings);
+36
View File
@@ -0,0 +1,36 @@
use std::fs;
use std::io;
use std::path::PathBuf;
use crate::ui::UiSettings;
const APP_DIR_NAME: &str = "desktop_dungeon_generator";
const SETTINGS_FILE_NAME: &str = "settings.json";
pub fn load_settings() -> Option<UiSettings> {
let path = settings_path()?;
let content = fs::read_to_string(path).ok()?;
serde_json::from_str::<UiSettings>(&content).ok()
}
pub fn save_settings(settings: &UiSettings) -> io::Result<()> {
let path = settings_path().ok_or_else(|| {
io::Error::new(
io::ErrorKind::NotFound,
"No OS application data directory found",
)
})?;
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
let json = serde_json::to_string_pretty(settings)
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
fs::write(path, json)
}
fn settings_path() -> Option<PathBuf> {
let base = dirs::data_local_dir().or_else(dirs::data_dir)?;
Some(base.join(APP_DIR_NAME).join(SETTINGS_FILE_NAME))
}
+10 -2
View File
@@ -1,14 +1,22 @@
use crate::seed; use crate::seed;
use eframe::egui; use eframe::egui;
use egui::RichText; use egui::RichText;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
enum Tab { enum Tab {
Generate, Generate,
Layout, Layout,
} }
#[derive(Debug, Clone)] impl Default for Tab {
fn default() -> Self {
Self::Generate
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct UiSettings { pub struct UiSettings {
pub seed: u64, pub seed: u64,
pub cols: usize, pub cols: usize,