diff --git a/Cargo.lock b/Cargo.lock index 0955fda9..0ae02b15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2435,6 +2435,7 @@ dependencies = [ "iced_baseview", "nih_plug", "nih_plug_assets", + "serde", ] [[package]] diff --git a/nih_plug_iced/Cargo.toml b/nih_plug_iced/Cargo.toml index bd8c7e1e..d0c96e64 100644 --- a/nih_plug_iced/Cargo.toml +++ b/nih_plug_iced/Cargo.toml @@ -62,3 +62,5 @@ crossbeam = "0.8" # Upstream doesn't work with the current iced version, this branch also contains # additional features iced_baseview = { git = "https://github.com/robbert-vdh/iced_baseview.git", branch = "feature/update-baseview", default_features = false } +# To make the state persistable +serde = { version = "1.0", features = ["derive"] } diff --git a/nih_plug_iced/src/lib.rs b/nih_plug_iced/src/lib.rs index 6fb0366d..d5af6195 100644 --- a/nih_plug_iced/src/lib.rs +++ b/nih_plug_iced/src/lib.rs @@ -92,7 +92,9 @@ use baseview::{WindowOpenOptions, WindowScalePolicy}; use crossbeam::atomic::AtomicCell; use crossbeam::channel; +use nih_plug::param::internals::PersistentField; use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle}; +use serde::{Deserialize, Serialize}; use std::fmt::Debug; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -229,13 +231,30 @@ pub trait IcedEditor: 'static + Send + Sync + Sized { } } -// TODO: Once we add resizing, we may want to be able to remember the GUI size. In that case we need -// to make this serializable (only restoring the size of course) so it can be persisted. +/// State for an `nih_plug_iced` editor. +#[derive(Serialize, Deserialize)] pub struct IcedState { + /// The window's size in logical pixels before applying `scale_factor`. + #[serde(with = "nih_plug::param::internals::serialize_atomic_cell")] size: AtomicCell<(u32, u32)>, + /// Whether the editor's window is currently open. + #[serde(skip)] open: AtomicBool, } +impl<'a> PersistentField<'a, IcedState> for Arc { + fn set(&self, new_value: IcedState) { + self.size.store(new_value.size.load()); + } + + fn map(&self, f: F) -> R + where + F: Fn(&IcedState) -> R, + { + f(self) + } +} + impl IcedState { /// Initialize the GUI's state. This value can be passed to [`create_iced_editor()`]. The window /// size is in logical pixels, so before it is multiplied by the DPI scaling factor.