Move nih_plug_vizia editor to its own module
This commit is contained in:
parent
c92c2a189b
commit
6ebc759706
126
nih_plug_vizia/src/editor.rs
Normal file
126
nih_plug_vizia/src/editor.rs
Normal file
|
@ -0,0 +1,126 @@
|
|||
//! The [`Editor`] trait implementation for Vizia editors.
|
||||
|
||||
use baseview::{WindowHandle, WindowScalePolicy};
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle};
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use vizia::prelude::*;
|
||||
|
||||
use crate::{assets, widgets, ViziaState, ViziaTheming};
|
||||
|
||||
/// An [`Editor`] implementation that calls an vizia draw loop.
|
||||
pub(crate) struct ViziaEditor {
|
||||
pub(crate) vizia_state: Arc<ViziaState>,
|
||||
/// The user's app function.
|
||||
pub(crate) app: Arc<dyn Fn(&mut Context, Arc<dyn GuiContext>) + 'static + Send + Sync>,
|
||||
/// What level of theming to apply. See [`ViziaEditorTheming`].
|
||||
pub(crate) theming: ViziaTheming,
|
||||
|
||||
/// The scaling factor reported by the host, if any. On macOS this will never be set and we
|
||||
/// should use the system scaling factor instead.
|
||||
pub(crate) scaling_factor: AtomicCell<Option<f32>>,
|
||||
}
|
||||
|
||||
impl Editor for ViziaEditor {
|
||||
fn spawn(
|
||||
&self,
|
||||
parent: ParentWindowHandle,
|
||||
context: Arc<dyn GuiContext>,
|
||||
) -> Box<dyn std::any::Any + Send> {
|
||||
let app = self.app.clone();
|
||||
let vizia_state = self.vizia_state.clone();
|
||||
let theming = self.theming;
|
||||
|
||||
let (unscaled_width, unscaled_height) = vizia_state.inner_logical_size();
|
||||
let system_scaling_factor = self.scaling_factor.load();
|
||||
let user_scale_factor = vizia_state.user_scale_factor();
|
||||
|
||||
let mut application = Application::new(move |cx| {
|
||||
// Set some default styles to match the iced integration
|
||||
if theming >= ViziaTheming::Custom {
|
||||
// NOTE: vizia's font rendering looks way too dark and thick. Going one font weight
|
||||
// lower seems to compensate for this.
|
||||
cx.set_default_font(assets::NOTO_SANS_LIGHT);
|
||||
cx.add_theme(include_str!("../assets/theme.css"));
|
||||
|
||||
// There doesn't seem to be any way to bundle styles with a widget, so we'll always
|
||||
// include the style sheet for our custom widgets at context creation
|
||||
widgets::register_theme(cx);
|
||||
}
|
||||
|
||||
// Any widget can change the parameters by emitting `ParamEvent` events. This model will
|
||||
// handle them automatically.
|
||||
widgets::ParamModel {
|
||||
context: context.clone(),
|
||||
}
|
||||
.build(cx);
|
||||
|
||||
// And we'll link `WindowEvent::ResizeWindow` and `WindowEvent::SetScale` events to our
|
||||
// `ViziaState`. We'll notify the host when any of these change.
|
||||
widgets::WindowModel {
|
||||
context: context.clone(),
|
||||
vizia_state: vizia_state.clone(),
|
||||
}
|
||||
.build(cx);
|
||||
|
||||
app(cx, context.clone())
|
||||
})
|
||||
.with_scale_policy(
|
||||
system_scaling_factor
|
||||
.map(|factor| WindowScalePolicy::ScaleFactor(factor as f64))
|
||||
.unwrap_or(WindowScalePolicy::SystemScaleFactor),
|
||||
)
|
||||
.inner_size((unscaled_width, unscaled_height))
|
||||
.user_scale_factor(user_scale_factor);
|
||||
|
||||
// This way the plugin can decide to use none of the built in theming
|
||||
if theming == ViziaTheming::None {
|
||||
application = application.ignore_default_theme();
|
||||
}
|
||||
|
||||
let window = application.open_parented(&parent);
|
||||
|
||||
self.vizia_state.open.store(true, Ordering::Release);
|
||||
Box::new(ViziaEditorHandle {
|
||||
vizia_state: self.vizia_state.clone(),
|
||||
window,
|
||||
})
|
||||
}
|
||||
|
||||
fn size(&self) -> (u32, u32) {
|
||||
// This includes the user scale factor if set, but not any HiDPI scaling
|
||||
self.vizia_state.scaled_logical_size()
|
||||
}
|
||||
|
||||
fn set_scale_factor(&self, factor: f32) -> bool {
|
||||
// We're making things a bit more complicated by having both a system scale factor, which is
|
||||
// used for HiDPI and also known to the host, and a user scale factor that the user can use
|
||||
// to arbitrarily resize the GUI
|
||||
self.scaling_factor.store(Some(factor));
|
||||
true
|
||||
}
|
||||
|
||||
fn param_values_changed(&self) {
|
||||
// TODO: Update the GUI when this happens, right now this happens automatically as a result
|
||||
// of of the reactivity
|
||||
}
|
||||
}
|
||||
|
||||
/// The window handle used for [`ViziaEditor`].
|
||||
struct ViziaEditorHandle {
|
||||
vizia_state: Arc<ViziaState>,
|
||||
window: WindowHandle,
|
||||
}
|
||||
|
||||
/// The window handle enum stored within 'WindowHandle' contains raw pointers. Is there a way around
|
||||
/// having this requirement?
|
||||
unsafe impl Send for ViziaEditorHandle {}
|
||||
|
||||
impl Drop for ViziaEditorHandle {
|
||||
fn drop(&mut self) {
|
||||
self.vizia_state.open.store(false, Ordering::Release);
|
||||
// XXX: This should automatically happen when the handle gets dropped, but apparently not
|
||||
self.window.close();
|
||||
}
|
||||
}
|
|
@ -3,10 +3,9 @@
|
|||
// See the comment in the main `nih_plug` crate
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
use baseview::{WindowHandle, WindowScalePolicy};
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use nih_plug::params::persist::PersistentField;
|
||||
use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle};
|
||||
use nih_plug::prelude::{Editor, GuiContext};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
@ -16,6 +15,7 @@ use vizia::prelude::*;
|
|||
pub use vizia;
|
||||
|
||||
pub mod assets;
|
||||
mod editor;
|
||||
pub mod vizia_assets;
|
||||
pub mod widgets;
|
||||
|
||||
|
@ -47,7 +47,7 @@ pub fn create_vizia_editor<F>(
|
|||
where
|
||||
F: Fn(&mut Context, Arc<dyn GuiContext>) + 'static + Send + Sync,
|
||||
{
|
||||
Some(Box::new(ViziaEditor {
|
||||
Some(Box::new(editor::ViziaEditor {
|
||||
vizia_state,
|
||||
app: Arc::new(app),
|
||||
theming,
|
||||
|
@ -161,119 +161,3 @@ impl ViziaState {
|
|||
self.open.load(Ordering::Acquire)
|
||||
}
|
||||
}
|
||||
|
||||
/// An [`Editor`] implementation that calls an vizia draw loop.
|
||||
struct ViziaEditor {
|
||||
vizia_state: Arc<ViziaState>,
|
||||
/// The user's app function.
|
||||
app: Arc<dyn Fn(&mut Context, Arc<dyn GuiContext>) + 'static + Send + Sync>,
|
||||
/// What level of theming to apply. See [`ViziaEditorTheming`].
|
||||
theming: ViziaTheming,
|
||||
|
||||
/// The scaling factor reported by the host, if any. On macOS this will never be set and we
|
||||
/// should use the system scaling factor instead.
|
||||
scaling_factor: AtomicCell<Option<f32>>,
|
||||
}
|
||||
|
||||
impl Editor for ViziaEditor {
|
||||
fn spawn(
|
||||
&self,
|
||||
parent: ParentWindowHandle,
|
||||
context: Arc<dyn GuiContext>,
|
||||
) -> Box<dyn std::any::Any + Send> {
|
||||
let app = self.app.clone();
|
||||
let vizia_state = self.vizia_state.clone();
|
||||
let theming = self.theming;
|
||||
|
||||
let (unscaled_width, unscaled_height) = vizia_state.inner_logical_size();
|
||||
let system_scaling_factor = self.scaling_factor.load();
|
||||
let user_scale_factor = vizia_state.user_scale_factor();
|
||||
|
||||
let mut application = Application::new(move |cx| {
|
||||
// Set some default styles to match the iced integration
|
||||
if theming >= ViziaTheming::Custom {
|
||||
// NOTE: vizia's font rendering looks way too dark and thick. Going one font weight
|
||||
// lower seems to compensate for this.
|
||||
cx.set_default_font(assets::NOTO_SANS_LIGHT);
|
||||
cx.add_theme(include_str!("../assets/theme.css"));
|
||||
|
||||
// There doesn't seem to be any way to bundle styles with a widget, so we'll always
|
||||
// include the style sheet for our custom widgets at context creation
|
||||
widgets::register_theme(cx);
|
||||
}
|
||||
|
||||
// Any widget can change the parameters by emitting `ParamEvent` events. This model will
|
||||
// handle them automatically.
|
||||
widgets::ParamModel {
|
||||
context: context.clone(),
|
||||
}
|
||||
.build(cx);
|
||||
|
||||
// And we'll link `WindowEvent::ResizeWindow` and `WindowEvent::SetScale` events to our
|
||||
// `ViziaState`. We'll notify the host when any of these change.
|
||||
widgets::WindowModel {
|
||||
context: context.clone(),
|
||||
vizia_state: vizia_state.clone(),
|
||||
}
|
||||
.build(cx);
|
||||
|
||||
app(cx, context.clone())
|
||||
})
|
||||
.with_scale_policy(
|
||||
system_scaling_factor
|
||||
.map(|factor| WindowScalePolicy::ScaleFactor(factor as f64))
|
||||
.unwrap_or(WindowScalePolicy::SystemScaleFactor),
|
||||
)
|
||||
.inner_size((unscaled_width, unscaled_height))
|
||||
.user_scale_factor(user_scale_factor);
|
||||
|
||||
// This way the plugin can decide to use none of the built in theming
|
||||
if theming == ViziaTheming::None {
|
||||
application = application.ignore_default_theme();
|
||||
}
|
||||
|
||||
let window = application.open_parented(&parent);
|
||||
|
||||
self.vizia_state.open.store(true, Ordering::Release);
|
||||
Box::new(ViziaEditorHandle {
|
||||
vizia_state: self.vizia_state.clone(),
|
||||
window,
|
||||
})
|
||||
}
|
||||
|
||||
fn size(&self) -> (u32, u32) {
|
||||
// This includes the user scale factor if set, but not any HiDPI scaling
|
||||
self.vizia_state.scaled_logical_size()
|
||||
}
|
||||
|
||||
fn set_scale_factor(&self, factor: f32) -> bool {
|
||||
// We're making things a bit more complicated by having both a system scale factor, which is
|
||||
// used for HiDPI and also known to the host, and a user scale factor that the user can use
|
||||
// to arbitrarily resize the GUI
|
||||
self.scaling_factor.store(Some(factor));
|
||||
true
|
||||
}
|
||||
|
||||
fn param_values_changed(&self) {
|
||||
// TODO: Update the GUI when this happens, right now this happens automatically as a result
|
||||
// of of the reactivity
|
||||
}
|
||||
}
|
||||
|
||||
/// The window handle used for [`ViziaEditor`].
|
||||
struct ViziaEditorHandle {
|
||||
vizia_state: Arc<ViziaState>,
|
||||
window: WindowHandle,
|
||||
}
|
||||
|
||||
/// The window handle enum stored within 'WindowHandle' contains raw pointers. Is there a way around
|
||||
/// having this requirement?
|
||||
unsafe impl Send for ViziaEditorHandle {}
|
||||
|
||||
impl Drop for ViziaEditorHandle {
|
||||
fn drop(&mut self) {
|
||||
self.vizia_state.open.store(false, Ordering::Release);
|
||||
// XXX: This should automatically happen when the handle gets dropped, but apparently not
|
||||
self.window.close();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue