Add a dedicated message and handler for parameters
Parameter widgets can send these messages to update parameters.
This commit is contained in:
parent
43590db8d0
commit
9f8bdfcfc4
|
@ -9,9 +9,13 @@ use std::fmt::Debug;
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::widgets::ParamMessage;
|
||||
|
||||
/// Re-export for convenience.
|
||||
pub use iced_baseview::*;
|
||||
|
||||
pub mod widgets;
|
||||
|
||||
/// Create an [`Editor`] instance using [iced](https://github.com/iced-rs/iced). The rough idea is
|
||||
/// that you implement [`IcedEditor`], which is roughly analogous to iced's regular [`Application`]
|
||||
/// trait except that it receives the [`GuiContext`] alongside its initialization flags so it can
|
||||
|
@ -42,7 +46,7 @@ pub fn create_iced_editor<E: IcedEditor>(
|
|||
pub trait IcedEditor: 'static + Send + Sync + Sized {
|
||||
/// See [`Application::Executor`]. You'll likely want to use [`crate::executor::Default`].
|
||||
type Executor: Executor;
|
||||
/// See [`Application::Message`].
|
||||
/// See [`Application::Message`]. You should have one variant containing a [`ParamMessage`].
|
||||
type Message: 'static + Clone + Debug + Send;
|
||||
/// See [`Application::Flags`].
|
||||
type InitializationFlags: 'static + Clone + Send + Sync;
|
||||
|
@ -53,7 +57,14 @@ pub trait IcedEditor: 'static + Send + Sync + Sized {
|
|||
context: Arc<dyn GuiContext>,
|
||||
) -> (Self, Command<Self::Message>);
|
||||
|
||||
/// See [`Application::update`].
|
||||
/// Return a reference to the GUI context.
|
||||
/// [`handle_param_message()`][Self::handle_param_message()] uses this to interact with the
|
||||
/// parameters.
|
||||
fn context(&self) -> &dyn GuiContext;
|
||||
|
||||
/// See [`Application::update`]. When receiving the variant that contains a
|
||||
/// [`widgets::ParamMessage`] you can call
|
||||
/// [`handle_param_message()`][Self::handle_param_message()] to handle the parameter update.
|
||||
fn update(
|
||||
&mut self,
|
||||
window: &mut WindowQueue,
|
||||
|
@ -87,6 +98,23 @@ pub trait IcedEditor: 'static + Send + Sync + Sized {
|
|||
fn renderer_settings() -> iced_baseview::renderer::settings::Settings {
|
||||
iced_baseview::renderer::settings::Settings::default()
|
||||
}
|
||||
|
||||
/// Handle a parameter update using the GUI context.
|
||||
fn handle_param_message(&self, message: ParamMessage) {
|
||||
// We can't use the fancy ParamSetter here because this needs to be type erased
|
||||
let context = self.context();
|
||||
match message {
|
||||
ParamMessage::BeginSetParameter(p) => unsafe { context.raw_begin_set_parameter(p) },
|
||||
ParamMessage::SetParameterNormalized(p, v) => unsafe {
|
||||
context.raw_set_parameter_normalized(p, v)
|
||||
},
|
||||
ParamMessage::ResetParameter(p) => unsafe {
|
||||
let default_value = context.raw_default_normalized_param_value(p);
|
||||
context.raw_set_parameter_normalized(p, default_value);
|
||||
},
|
||||
ParamMessage::EndSetParameter(p) => unsafe { context.raw_end_set_parameter(p) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Once we add resizing, we may want to be able to remember the GUI size. In that case we need
|
||||
|
|
22
nih_plug_iced/src/widgets.rs
Normal file
22
nih_plug_iced/src/widgets.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
//! Widgets and utilities for making widgets to integrate iced with NIH-plug.
|
||||
|
||||
use nih_plug::param::internals::ParamPtr;
|
||||
|
||||
/// A message to update a parameter value. Since NIH-plug manages the parameters, interacting with
|
||||
/// parameter values with iced works a little different from updating any other state. This main
|
||||
/// [`IcedEditor`][super::IcedEditor] should have a [`Message`][super::IcedEditor::Message] variant
|
||||
/// containing this `ParamMessage`. When it receives one of those messages, it can pass it through
|
||||
/// to [`self.handle_param_message()`][super::IcedEditor::handle_param_message].
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ParamMessage {
|
||||
/// Begin an automation gesture for a parameter.
|
||||
BeginSetParameter(ParamPtr),
|
||||
/// Set a parameter to a new normalized value. This needs to be surrounded by a matching
|
||||
/// `BeginSetParameter` and `EndSetParameter`.
|
||||
SetParameterNormalized(ParamPtr, f32),
|
||||
/// Reset a parameter to its default value. This needs to be surrounded by a matching
|
||||
/// `BeginSetParameter` and `EndSetParameter`.
|
||||
ResetParameter(ParamPtr),
|
||||
/// End an automation gesture for a parameter.
|
||||
EndSetParameter(ParamPtr),
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use nih_plug::prelude::{Editor, GuiContext};
|
||||
use nih_plug_iced::widgets::ParamMessage;
|
||||
use nih_plug_iced::{create_iced_editor, Command, Element, IcedEditor, IcedState};
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
@ -38,10 +39,14 @@ struct DiopserEditor {
|
|||
context: Arc<dyn GuiContext>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum EditorMessage {
|
||||
ParamUpdate(ParamMessage),
|
||||
}
|
||||
|
||||
impl IcedEditor for DiopserEditor {
|
||||
type Executor = nih_plug_iced::executor::Default;
|
||||
// TODO:
|
||||
type Message = ();
|
||||
type Message = EditorMessage;
|
||||
type InitializationFlags = Pin<Arc<DiopserParams>>;
|
||||
|
||||
fn new(
|
||||
|
@ -53,12 +58,19 @@ impl IcedEditor for DiopserEditor {
|
|||
(editor, Command::none())
|
||||
}
|
||||
|
||||
fn context(&self) -> &dyn GuiContext {
|
||||
self.context.as_ref()
|
||||
}
|
||||
|
||||
fn update(
|
||||
&mut self,
|
||||
window: &mut nih_plug_iced::WindowQueue,
|
||||
_window: &mut nih_plug_iced::WindowQueue,
|
||||
message: Self::Message,
|
||||
) -> Command<Self::Message> {
|
||||
// TODO:
|
||||
match message {
|
||||
EditorMessage::ParamUpdate(message) => self.handle_param_message(message),
|
||||
}
|
||||
|
||||
Command::none()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue