mirror of
https://github.com/robbert-vdh/nih-plug.git
synced 2026-07-01 02:36:54 +00:00
Add an egui editor adapter
This commit is contained in:
17
nih_plug_egui/Cargo.toml
Normal file
17
nih_plug_egui/Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "nih_plug_egui"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
authors = ["Robbert van der Helm <mail@robbertvanderhelm.nl>"]
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
description = "An adapter to use egui GUIs with NIH-plug"
|
||||
|
||||
[dependencies]
|
||||
nih_plug = { path = ".." }
|
||||
|
||||
baseview = { git = "https://github.com/RustAudio/baseview.git" }
|
||||
crossbeam = "0.8"
|
||||
egui = "0.16"
|
||||
# Upstream doesn't work with the current baseview and egui versions
|
||||
egui-baseview = { git = "https://github.com/robbert-vdh/egui-baseview.git", branch = "fix/update-dependencies" }
|
||||
5
nih_plug_egui/README.md
Normal file
5
nih_plug_egui/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# NIH-plug: egui support
|
||||
|
||||
This provides an adapter to create [egui](https://github.com/emilk/egui) based
|
||||
GUIs with NIH-plug through
|
||||
[egui-baseview](https://github.com/BillyDM/egui-baseview).
|
||||
109
nih_plug_egui/src/lib.rs
Normal file
109
nih_plug_egui/src/lib.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
// nih-plug: plugins, but rewritten in Rust
|
||||
// Copyright (C) 2022 Robbert van der Helm
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//! [egui](https://github.com/emilk/egui) editor support for NIH plug.
|
||||
//!
|
||||
//! TODO: Proper usage example
|
||||
|
||||
use baseview::{Size, WindowHandle, WindowOpenOptions, WindowScalePolicy};
|
||||
use egui::CtxRef;
|
||||
use egui_baseview::{EguiWindow, Queue, RenderSettings, Settings};
|
||||
use nih_plug::{Editor, EditorWindowHandle, GuiContext};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Re-export for convenience.
|
||||
pub use crossbeam::atomic::AtomicCell;
|
||||
|
||||
/// Create an [Editor] instance using an [::egui] GUI. The size passed to this function is the GUI's
|
||||
/// intiial size, and this is kept in sync whenever the GUI gets resized. You should return the same
|
||||
/// size value in your plugin' [nih_plug::Plugin::editor_size()] implementation..
|
||||
//
|
||||
// TODO: Figure out if the build function and [Queue] things we're omitting now are actually useful
|
||||
// to the user
|
||||
// TODO: Provide 'advanced' versions that expose more of the low level settings and details here
|
||||
// TODO: DPI scaling, this needs to be implemented on the framework level
|
||||
pub fn create_egui_editor<'context, T, U>(
|
||||
parent: EditorWindowHandle,
|
||||
context: Arc<dyn GuiContext + 'context>,
|
||||
size: Arc<AtomicCell<(u32, u32)>>,
|
||||
initial_state: T,
|
||||
mut update: U,
|
||||
) -> Option<Box<dyn Editor + 'context>>
|
||||
where
|
||||
T: 'static + Send,
|
||||
U: FnMut(&CtxRef, &dyn GuiContext, &mut T) + 'static + Send,
|
||||
{
|
||||
// TODO: Also pass the context reference to the update callback
|
||||
let (width, height) = size.load();
|
||||
let window = EguiWindow::open_parented(
|
||||
&parent,
|
||||
Settings {
|
||||
window: WindowOpenOptions {
|
||||
title: String::from("egui window"),
|
||||
size: Size::new(width as f64, height as f64),
|
||||
// TODO: What happens when we use the system scale factor here? I'd assume this
|
||||
// would work everywhere, even if the window may be tiny in some cases.
|
||||
scale: WindowScalePolicy::ScaleFactor(1.0),
|
||||
},
|
||||
render_settings: RenderSettings {
|
||||
version: (3, 2),
|
||||
red_bits: 8,
|
||||
blue_bits: 8,
|
||||
green_bits: 8,
|
||||
// If the window was not created with the correct visual, then specifying 8 bits
|
||||
// here will cause creating the context to fail
|
||||
alpha_bits: 0,
|
||||
depth_bits: 24,
|
||||
stencil_bits: 8,
|
||||
samples: None,
|
||||
srgb: true,
|
||||
double_buffer: true,
|
||||
vsync: true,
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
initial_state,
|
||||
|_, _, _| {},
|
||||
move |ctx, _, state| update(ctx, context.as_ref(), state),
|
||||
);
|
||||
|
||||
// There's no error handling here, so let's just pray it worked
|
||||
if window.is_open() {
|
||||
Some(Box::new(EguiEditor {
|
||||
_window: window,
|
||||
size,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// An [Editor] implementation that calls an egui draw loop.
|
||||
pub struct EguiEditor {
|
||||
_window: WindowHandle,
|
||||
size: Arc<AtomicCell<(u32, u32)>>,
|
||||
}
|
||||
|
||||
/// The window handle enum stored within 'WindowHandle' contains raw pointers. Is there a way around
|
||||
/// having this requirement?
|
||||
unsafe impl Send for EguiEditor {}
|
||||
unsafe impl Sync for EguiEditor {}
|
||||
|
||||
impl Editor for EguiEditor {
|
||||
fn size(&self) -> (u32, u32) {
|
||||
self.size.load()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user