From 748d2130c2e8c91021e1f403e0938193d1db54a1 Mon Sep 17 00:00:00 2001 From: Lucas Meurer Date: Sat, 27 Apr 2024 13:46:56 +0200 Subject: [PATCH 1/4] Add option to specify persistence path --- crates/eframe/src/epi.rs | 8 ++++++++ crates/eframe/src/native/epi_integration.rs | 11 +++++++++++ crates/eframe/src/native/file_storage.rs | 2 +- crates/eframe/src/native/glow_integration.rs | 18 +++++++++++------- crates/eframe/src/native/wgpu_integration.rs | 18 +++++++++++------- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/crates/eframe/src/epi.rs b/crates/eframe/src/epi.rs index e7b53691cda9..9d06645b9c7e 100644 --- a/crates/eframe/src/epi.rs +++ b/crates/eframe/src/epi.rs @@ -362,6 +362,10 @@ pub struct NativeOptions { /// Controls whether or not the native window position and size will be /// persisted (only if the "persistence" feature is enabled). pub persist_window: bool, + + /// The folder where `eframe` will store the app state. If not set, eframe will get the paths + /// from [directories_next]. + pub persistence_path: Option, } #[cfg(not(target_arch = "wasm32"))] @@ -379,6 +383,8 @@ impl Clone for NativeOptions { #[cfg(feature = "wgpu")] wgpu_options: self.wgpu_options.clone(), + persistence_path: self.persistence_path.clone(), + ..*self } } @@ -418,6 +424,8 @@ impl Default for NativeOptions { wgpu_options: egui_wgpu::WgpuConfiguration::default(), persist_window: true, + + persistence_path: None, } } } diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index b09f0f0e0c79..c4f56575b5f8 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -1,6 +1,8 @@ //! Common tools used by [`super::glow_integration`] and [`super::wgpu_integration`]. use web_time::Instant; + +use std::path::PathBuf; use winit::event_loop::EventLoopWindowTarget; use raw_window_handle::{HasDisplayHandle as _, HasWindowHandle as _}; @@ -129,6 +131,15 @@ pub fn create_storage(_app_name: &str) -> Option> { None } +pub fn create_storage_with_file(file: impl Into) -> Option> { + #[cfg(feature = "persistence")] + return Some(Box::new( + super::file_storage::FileStorage::from_ron_filepath(file), + )); + #[cfg(not(feature = "persistence"))] + None +} + // ---------------------------------------------------------------------------- /// Everything needed to make a winit-based integration for [`epi`]. diff --git a/crates/eframe/src/native/file_storage.rs b/crates/eframe/src/native/file_storage.rs index 51c668abdebc..970c35a4f41c 100644 --- a/crates/eframe/src/native/file_storage.rs +++ b/crates/eframe/src/native/file_storage.rs @@ -41,7 +41,7 @@ impl Drop for FileStorage { impl FileStorage { /// Store the state in this .ron file. - fn from_ron_filepath(ron_filepath: impl Into) -> Self { + pub(crate) fn from_ron_filepath(ron_filepath: impl Into) -> Self { crate::profile_function!(); let ron_filepath: PathBuf = ron_filepath.into(); log::debug!("Loading app state from {:?}…", ron_filepath); diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index f08ed14d6235..9a67e4af3d9e 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -195,13 +195,17 @@ impl GlowWinitApp { ) -> Result<&mut GlowWinitRunning> { crate::profile_function!(); - let storage = epi_integration::create_storage( - self.native_options - .viewport - .app_id - .as_ref() - .unwrap_or(&self.app_name), - ); + let storage = if let Some(file) = &self.native_options.persistence_path { + epi_integration::create_storage_with_file(file) + } else { + epi_integration::create_storage( + self.native_options + .viewport + .app_id + .as_ref() + .unwrap_or(&self.app_name), + ) + }; let egui_ctx = create_egui_context(storage.as_deref()); diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index 1287ce8a01f5..2276d7cb0374 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -420,13 +420,17 @@ impl WinitApp for WgpuWinitApp { self.recreate_window(event_loop, running); running } else { - let storage = epi_integration::create_storage( - self.native_options - .viewport - .app_id - .as_ref() - .unwrap_or(&self.app_name), - ); + let storage = if let Some(file) = &self.native_options.persistence_path { + epi_integration::create_storage_with_file(file) + } else { + epi_integration::create_storage( + self.native_options + .viewport + .app_id + .as_ref() + .unwrap_or(&self.app_name), + ) + }; let egui_ctx = winit_integration::create_egui_context(storage.as_deref()); let (window, builder) = create_window( &egui_ctx, From 1a2e7c29a841f4087cb22645b4730ceed68d9298 Mon Sep 17 00:00:00 2001 From: Lucas Meurer Date: Mon, 27 May 2024 16:50:08 +0200 Subject: [PATCH 2/4] Fix lint error --- crates/eframe/src/native/epi_integration.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index c4f56575b5f8..ad8d9ba10bec 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -131,10 +131,10 @@ pub fn create_storage(_app_name: &str) -> Option> { None } -pub fn create_storage_with_file(file: impl Into) -> Option> { +pub fn create_storage_with_file(_file: impl Into) -> Option> { #[cfg(feature = "persistence")] return Some(Box::new( - super::file_storage::FileStorage::from_ron_filepath(file), + super::file_storage::FileStorage::from_ron_filepath(_file), )); #[cfg(not(feature = "persistence"))] None From cd222ec257736db67331cdd09a808b84566d7aa3 Mon Sep 17 00:00:00 2001 From: Lucas Meurer Date: Mon, 27 May 2024 16:54:19 +0200 Subject: [PATCH 3/4] Link NativeOptions::persitence_path from App::save --- crates/eframe/src/epi.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/eframe/src/epi.rs b/crates/eframe/src/epi.rs index 9d06645b9c7e..ecfff3fe6cea 100644 --- a/crates/eframe/src/epi.rs +++ b/crates/eframe/src/epi.rs @@ -150,6 +150,7 @@ pub trait App { /// On web the state is stored to "Local Storage". /// /// On native the path is picked using [`crate::storage_dir`]. + /// The path can be customized via [`NativeOptions::persistence_path`]. fn save(&mut self, _storage: &mut dyn Storage) {} /// Called once on shutdown, after [`Self::save`]. From 6dd62554992d53e087344197691e67fdff6f6ab5 Mon Sep 17 00:00:00 2001 From: Lucas Meurer Date: Mon, 27 May 2024 17:29:36 +0200 Subject: [PATCH 4/4] Clippy --- crates/eframe/src/native/epi_integration.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index ad8d9ba10bec..7be09c164ac7 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -131,6 +131,7 @@ pub fn create_storage(_app_name: &str) -> Option> { None } +#[allow(clippy::unnecessary_wraps)] pub fn create_storage_with_file(_file: impl Into) -> Option> { #[cfg(feature = "persistence")] return Some(Box::new(