made settings persistant
This commit is contained in:
@@ -5,3 +5,6 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
eframe = "0.31"
|
eframe = "0.31"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
dirs = "6"
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
|
|||||||
@@ -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))
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user