use std::sync::{ Arc, atomic::{AtomicBool, Ordering}, }; use baseview::WindowHandle; use crossbeam::atomic::AtomicCell; use nih_plug::params::persist::PersistentField; use serde::{Deserialize, Serialize}; use crate::window::EditorWindow; #[derive(Debug, Serialize, Deserialize)] pub struct EditorState { /// The window's size in logical pixels before applying `scale_factor`. #[serde(with = "nih_plug::params::persist::serialize_atomic_cell")] pub size: AtomicCell<(u32, u32)>, /// Whether the editor's window is currently open. #[serde(skip)] pub open: AtomicBool, } impl EditorState { pub fn from_size(size: (u32, u32)) -> Arc { Arc::new(Self { size: AtomicCell::new(( (size.0 as f32 * EditorWindow::VIRTUAL_SCALE) as u32, (size.1 as f32 * EditorWindow::VIRTUAL_SCALE) as u32, )), open: AtomicBool::new(false), }) } pub fn size(&self) -> (u32, u32) { self.size.load() } pub fn is_open(&self) -> bool { self.open.load(Ordering::Acquire) } } impl<'a> PersistentField<'a, EditorState> for Arc { fn set(&self, new_value: EditorState) { self.size.store(new_value.size.load()); } fn map(&self, f: F) -> R where F: Fn(&EditorState) -> R, { f(self) } } pub struct EditorHandle { pub state: Arc, pub window: WindowHandle, } unsafe impl Send for EditorHandle {} impl Drop for EditorHandle { fn drop(&mut self) { self.state.open.store(false, Ordering::Release); self.window.close(); } }