Files
Oxide/docs/settings.md
T
Homer Simpson 9eead719b0 Import Oxide engine (Stages 0–10) under MIT license
Full project snapshot migrated to new Gitea remote without history:
engine, editor, physics, script, examples, tests, docs, and assets.
Relicensed from GPLv3 to MIT and updated repo URLs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 20:41:02 +02:00

2.8 KiB

Settings & Preferences Framework

oxide_engine::settings is the engine's unified, serialized configuration store. The engine, the editor, and every module register typed sections; the framework persists them all to RON and restores them — without any central code knowing the sections' shapes. It is the backbone of the editor's Preferences window and of per-module settings.

Sections

A section is any plain serde-serializable struct with a Default. Register it once under a name and the store owns a typed instance:

use oxide_engine::settings::Settings;
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Default)]
struct EditorPrefs { theme: String, grid: bool }

let mut settings = Settings::new();
settings.register::<EditorPrefs>("editor");

// Typed read/write.
settings.get_mut::<EditorPrefs>("editor").unwrap().theme = "dark".into();
assert_eq!(settings.get::<EditorPrefs>("editor").unwrap().theme, "dark");

set replaces a section's value (only if the registered type matches), and reset returns it to Default. Accessing a section as the wrong type returns None rather than panicking.

Persisting

Every section serializes to a name → RON map via export, and import loads matching sections back. This map is exactly the shape a Project stores, so per-project settings round-trip through the project file:

# use oxide_engine::settings::Settings;
# use serde::{Serialize, Deserialize};
# #[derive(Serialize, Deserialize, Default)] struct EditorPrefs { theme: String }
# let mut settings = Settings::new();
# settings.register::<EditorPrefs>("editor");
let saved = settings.export();          // BTreeMap<String, String>

let mut restored = Settings::new();
restored.register::<EditorPrefs>("editor");
restored.import(&saved);                // matching sections restored

import is deliberately lenient: an unknown section (e.g. one owned by a disabled module) is ignored, and a malformed section is skipped, leaving its current value. This means a project saved with a module enabled still opens cleanly with that module disabled, and vice-versa.

How the layers fit together

Scope Lives where Persisted to
Engine preferences (render/quality defaults) a Settings section global prefs file / project
Editor preferences (theme, layout, shortcuts) a Settings section global editor prefs file
Per-module settings each module registers a section the project it's enabled in

Project stores the per-project subset (set_settings_section / settings_section hold the same RON blobs export/import produce). The editor keeps its global preferences in a separate file using the same Settings API.