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
|
// See the comment in the main `nih_plug` crate
|
||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
|
|
||||||
use baseview::{WindowHandle, WindowScalePolicy};
|
|
||||||
use crossbeam::atomic::AtomicCell;
|
use crossbeam::atomic::AtomicCell;
|
||||||
use nih_plug::params::persist::PersistentField;
|
use nih_plug::params::persist::PersistentField;
|
||||||
use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle};
|
use nih_plug::prelude::{Editor, GuiContext};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -16,6 +15,7 @@ use vizia::prelude::*;
|
||||||
pub use vizia;
|
pub use vizia;
|
||||||
|
|
||||||
pub mod assets;
|
pub mod assets;
|
||||||
|
mod editor;
|
||||||
pub mod vizia_assets;
|
pub mod vizia_assets;
|
||||||
pub mod widgets;
|
pub mod widgets;
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ pub fn create_vizia_editor<F>(
|
||||||
where
|
where
|
||||||
F: Fn(&mut Context, Arc<dyn GuiContext>) + 'static + Send + Sync,
|
F: Fn(&mut Context, Arc<dyn GuiContext>) + 'static + Send + Sync,
|
||||||
{
|
{
|
||||||
Some(Box::new(ViziaEditor {
|
Some(Box::new(editor::ViziaEditor {
|
||||||
vizia_state,
|
vizia_state,
|
||||||
app: Arc::new(app),
|
app: Arc::new(app),
|
||||||
theming,
|
theming,
|
||||||
|
@ -161,119 +161,3 @@ impl ViziaState {
|
||||||
self.open.load(Ordering::Acquire)
|
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