#![allow(clippy::type_complexity)]
use crossbeam::atomic::AtomicCell;
use egui::{Context, Ui};
use nice_plug_core::context::gui::ParamSetter;
use nice_plug_core::editor::Editor;
use nice_plug_core::params::persist::PersistentField;
use parking_lot::Mutex;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
#[cfg(not(any(feature = "opengl", feature = "wgpu")))]
compile_error!("There's currently no software rendering support for egui");
pub use egui_baseview::*;
#[cfg(all(feature = "opengl", not(feature = "wgpu")))]
pub use baseview::gl::{GlConfig, Profile};
mod editor;
pub mod resizable_window;
pub mod widgets;
#[derive(Default, Debug, Clone)]
pub struct EguiSettings {
pub graphics_config: GraphicsConfig,
#[cfg(all(feature = "opengl", not(feature = "wgpu")))]
pub enable_vsync_on_x11: bool,
#[cfg(all(feature = "opengl", not(feature = "wgpu")))]
pub gl_config: GlConfig,
}
pub fn create_egui_editor<T, B, U>(
egui_state: Arc<EguiState>,
user_state: T,
settings: EguiSettings,
build: B,
update: U,
) -> Option<Box<dyn Editor>>
where
T: 'static + Send,
B: Fn(&Context, &mut Queue, &mut T) + 'static + Send + Sync,
U: Fn(&mut Ui, &ParamSetter, &mut Queue, &mut T) + 'static + Send + Sync,
{
Some(Box::new(editor::EguiEditor {
egui_state,
user_state: Arc::new(Mutex::new(user_state)),
settings: Arc::new(settings),
build: Arc::new(build),
update: Arc::new(update),
#[cfg(target_os = "macos")]
scaling_factor: AtomicCell::new(None),
#[cfg(not(target_os = "macos"))]
scaling_factor: AtomicCell::new(Some(1.0)),
}))
}
#[derive(Debug, Serialize, Deserialize)]
pub struct EguiState {
#[serde(with = "nice_plug_core::params::persist::serialize_atomic_cell")]
size: AtomicCell<(u32, u32)>,
#[serde(skip)]
requested_size: AtomicCell<Option<(u32, u32)>>,
#[serde(skip)]
open: AtomicBool,
}
impl<'a> PersistentField<'a, EguiState> for Arc<EguiState> {
fn set(&self, new_value: EguiState) {
self.size.store(new_value.size.load());
}
fn map<F, R>(&self, f: F) -> R
where
F: Fn(&EguiState) -> R,
{
f(self)
}
}
impl EguiState {
pub fn from_size(width: u32, height: u32) -> Arc<EguiState> {
Arc::new(EguiState {
size: AtomicCell::new((width, height)),
requested_size: Default::default(),
open: AtomicBool::new(false),
})
}
pub fn size(&self) -> (u32, u32) {
self.size.load()
}
pub fn is_open(&self) -> bool {
self.open.load(Ordering::Acquire)
}
pub fn set_requested_size(&self, new_size: (u32, u32)) {
self.requested_size.store(Some(new_size));
}
}