fyroxed_base/settings/
mod.rs1use crate::{
22 fyrox::core::{log::Log, reflect::prelude::*},
23 settings::{
24 build::BuildSettings, camera::CameraSettings, debugging::DebuggingSettings,
25 general::GeneralSettings, graphics::GraphicsSettings, keys::KeyBindings, log::LogSettings,
26 model::ModelSettings, move_mode::MoveInteractionModeSettings, navmesh::NavmeshSettings,
27 recent::RecentFiles, rotate_mode::RotateInteractionModeSettings, scene::SceneSettings,
28 selection::SelectionSettings, windows::WindowsSettings,
29 },
30};
31use ron::ser::PrettyConfig;
32use serde::{Deserialize, Serialize};
33use std::{
34 collections::HashMap,
35 fmt::Display,
36 fs::File,
37 io::Write,
38 ops::{Deref, DerefMut},
39 path::PathBuf,
40 sync::mpsc::Sender,
41};
42
43pub mod build;
44pub mod camera;
45pub mod debugging;
46pub mod general;
47pub mod graphics;
48pub mod keys;
49pub mod log;
50pub mod model;
51pub mod move_mode;
52pub mod navmesh;
53pub mod recent;
54pub mod rotate_mode;
55pub mod scene;
56pub mod selection;
57pub mod windows;
58
59#[derive(Deserialize, Serialize, PartialEq, Clone, Default, Debug, Reflect)]
60pub struct SettingsData {
61 #[reflect(tag = "Group.Selection")]
62 pub selection: SelectionSettings,
63 #[reflect(tag = "Group.Graphics")]
64 pub graphics: GraphicsSettings,
65 #[reflect(tag = "Group.Build")]
66 #[serde(default)]
67 pub build: BuildSettings,
68 #[reflect(tag = "Group.General")]
69 #[serde(default)]
70 pub general: GeneralSettings,
71 #[reflect(tag = "Group.Debugging")]
72 pub debugging: DebuggingSettings,
73 #[reflect(tag = "Group.MoveMode")]
74 pub move_mode_settings: MoveInteractionModeSettings,
75 #[reflect(tag = "Group.RotateMode")]
76 pub rotate_mode_settings: RotateInteractionModeSettings,
77 #[reflect(tag = "Group.Model")]
78 pub model: ModelSettings,
79 #[reflect(tag = "Group.Camera")]
80 pub camera: CameraSettings,
81 #[reflect(tag = "Group.Navmesh")]
82 pub navmesh: NavmeshSettings,
83 #[reflect(tag = "Group.KeyBindings")]
84 pub key_bindings: KeyBindings,
85 #[reflect(tag = "Group.Log")]
86 #[reflect(hidden)]
87 #[serde(default)]
88 pub log: LogSettings,
89 #[reflect(hidden)]
90 pub scene_settings: HashMap<PathBuf, SceneSettings>,
91 #[reflect(hidden)]
92 pub recent: RecentFiles,
93 #[serde(default)]
94 #[reflect(hidden)]
95 pub windows: WindowsSettings,
96}
97
98pub enum SettingsMessage {
99 Changed,
100}
101
102#[derive(Default)]
103pub struct Settings {
104 settings: SettingsData,
105 need_save: bool,
106 pub subscribers: Vec<Sender<SettingsMessage>>,
107}
108
109impl Deref for Settings {
110 type Target = SettingsData;
111
112 fn deref(&self) -> &Self::Target {
113 &self.settings
114 }
115}
116
117impl DerefMut for Settings {
118 fn deref_mut(&mut self) -> &mut Self::Target {
119 self.need_save = true;
120
121 self.subscribers
122 .retain_mut(|subscriber| subscriber.send(SettingsMessage::Changed).is_ok());
123
124 &mut self.settings
125 }
126}
127
128impl Settings {
129 pub fn load() -> Result<Self, SettingsError> {
130 let settings = SettingsData::load()?;
131 Log::set_log_info(settings.log.log_info);
132 Log::set_log_warning(settings.log.log_warning);
133 Log::set_log_error(settings.log.log_error);
134 Ok(Settings {
135 settings,
136 need_save: false,
137 subscribers: Default::default(),
138 })
139 }
140
141 pub fn data_mut(&mut self) -> &mut SettingsData {
142 &mut self.settings
143 }
144
145 pub fn force_save(&mut self) {
146 self.need_save = false;
147 Log::verify(self.settings.save());
148 }
149
150 pub fn try_save(&mut self) -> bool {
151 if self.need_save {
152 self.need_save = false;
153 Log::verify(self.settings.save());
154 true
155 } else {
156 false
157 }
158 }
159}
160
161#[derive(Debug)]
162pub enum SettingsError {
163 Io(std::io::Error),
164 RonSpanned(ron::error::SpannedError),
165 Ron(ron::Error),
166}
167
168impl std::error::Error for SettingsError {}
169
170impl Display for SettingsError {
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 match self {
173 SettingsError::Io(error) => Display::fmt(error, f),
174 SettingsError::RonSpanned(error) => Display::fmt(error, f),
175 SettingsError::Ron(error) => Display::fmt(error, f),
176 }
177 }
178}
179
180impl From<std::io::Error> for SettingsError {
181 fn from(e: std::io::Error) -> Self {
182 Self::Io(e)
183 }
184}
185
186impl From<ron::error::SpannedError> for SettingsError {
187 fn from(e: ron::error::SpannedError) -> Self {
188 Self::RonSpanned(e)
189 }
190}
191
192impl From<ron::Error> for SettingsError {
193 fn from(e: ron::Error) -> Self {
194 Self::Ron(e)
195 }
196}
197
198impl SettingsData {
199 const FILE_NAME: &'static str = "settings.ron";
200
201 fn full_path() -> PathBuf {
202 Self::FILE_NAME.into()
203 }
204
205 pub fn load() -> Result<Self, SettingsError> {
206 let file = File::open(Self::full_path())?;
207 Ok(ron::de::from_reader(file)?)
208 }
209
210 fn save(&mut self) -> Result<(), SettingsError> {
211 let mut file = File::create(Self::full_path())?;
212 self.recent.deduplicate_and_refresh();
213
214 file.write_all(ron::ser::to_string_pretty(self, PrettyConfig::default())?.as_bytes())?;
215
216 Ok(())
217 }
218}