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::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::widgets::ParamMessage;
|
||||||
|
|
||||||
/// Re-export for convenience.
|
/// Re-export for convenience.
|
||||||
pub use iced_baseview::*;
|
pub use iced_baseview::*;
|
||||||
|
|
||||||
|
pub mod widgets;
|
||||||
|
|
||||||
/// Create an [`Editor`] instance using [iced](https://github.com/iced-rs/iced). The rough idea is
|
/// 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`]
|
/// 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
|
/// 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 {
|
pub trait IcedEditor: 'static + Send + Sync + Sized {
|
||||||
/// See [`Application::Executor`]. You'll likely want to use [`crate::executor::Default`].
|
/// See [`Application::Executor`]. You'll likely want to use [`crate::executor::Default`].
|
||||||
type Executor: Executor;
|
type Executor: Executor;
|
||||||
/// See [`Application::Message`].
|
/// See [`Application::Message`]. You should have one variant containing a [`ParamMessage`].
|
||||||
type Message: 'static + Clone + Debug + Send;
|
type Message: 'static + Clone + Debug + Send;
|
||||||
/// See [`Application::Flags`].
|
/// See [`Application::Flags`].
|
||||||
type InitializationFlags: 'static + Clone + Send + Sync;
|
type InitializationFlags: 'static + Clone + Send + Sync;
|
||||||
|
@ -53,7 +57,14 @@ pub trait IcedEditor: 'static + Send + Sync + Sized {
|
||||||
context: Arc<dyn GuiContext>,
|
context: Arc<dyn GuiContext>,
|
||||||
) -> (Self, Command<Self::Message>);
|
) -> (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(
|
fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
window: &mut WindowQueue,
|
window: &mut WindowQueue,
|
||||||
|
@ -87,6 +98,23 @@ pub trait IcedEditor: 'static + Send + Sync + Sized {
|
||||||
fn renderer_settings() -> iced_baseview::renderer::settings::Settings {
|
fn renderer_settings() -> iced_baseview::renderer::settings::Settings {
|
||||||
iced_baseview::renderer::settings::Settings::default()
|
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
|
// 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/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use nih_plug::prelude::{Editor, GuiContext};
|
use nih_plug::prelude::{Editor, GuiContext};
|
||||||
|
use nih_plug_iced::widgets::ParamMessage;
|
||||||
use nih_plug_iced::{create_iced_editor, Command, Element, IcedEditor, IcedState};
|
use nih_plug_iced::{create_iced_editor, Command, Element, IcedEditor, IcedState};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -38,10 +39,14 @@ struct DiopserEditor {
|
||||||
context: Arc<dyn GuiContext>,
|
context: Arc<dyn GuiContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum EditorMessage {
|
||||||
|
ParamUpdate(ParamMessage),
|
||||||
|
}
|
||||||
|
|
||||||
impl IcedEditor for DiopserEditor {
|
impl IcedEditor for DiopserEditor {
|
||||||
type Executor = nih_plug_iced::executor::Default;
|
type Executor = nih_plug_iced::executor::Default;
|
||||||
// TODO:
|
type Message = EditorMessage;
|
||||||
type Message = ();
|
|
||||||
type InitializationFlags = Pin<Arc<DiopserParams>>;
|
type InitializationFlags = Pin<Arc<DiopserParams>>;
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
|
@ -53,12 +58,19 @@ impl IcedEditor for DiopserEditor {
|
||||||
(editor, Command::none())
|
(editor, Command::none())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn context(&self) -> &dyn GuiContext {
|
||||||
|
self.context.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
window: &mut nih_plug_iced::WindowQueue,
|
_window: &mut nih_plug_iced::WindowQueue,
|
||||||
message: Self::Message,
|
message: Self::Message,
|
||||||
) -> Command<Self::Message> {
|
) -> Command<Self::Message> {
|
||||||
// TODO:
|
match message {
|
||||||
|
EditorMessage::ParamUpdate(message) => self.handle_param_message(message),
|
||||||
|
}
|
||||||
|
|
||||||
Command::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue