diff --git a/nih_plug_vizia/src/widgets.rs b/nih_plug_vizia/src/widgets.rs index 3fcd712b..38d405f4 100644 --- a/nih_plug_vizia/src/widgets.rs +++ b/nih_plug_vizia/src/widgets.rs @@ -5,16 +5,38 @@ //! None of these widgets are finalized, and their sizes or looks can change at any point. Feel free //! to copy the widgets and modify them to your personal taste. -use nih_plug::{context::GuiContext, param::internals::ParamPtr}; +use nih_plug::param::internals::ParamPtr; +use nih_plug::prelude::{GuiContext, Param}; use std::sync::Arc; -use vizia::Model; +use vizia::{Message, Model}; /// An event that updates a parameter's value. Since NIH-plug manages the parameters, interacting /// with parameter values with VIZIA works a little different from updating any other state. These /// events are automatically handled by `nih_plug_vizia`. +/// +/// Call the [`upcast()`][Self::upcast()] method to be able to emit this event through a +/// [`Context`][vizia::Context]. #[derive(Debug, Clone, Copy)] -pub enum ParamEvent { +pub enum ParamEvent<'a, P: Param> { + /// Begin an automation gesture for a parameter. + BeginSetParameter(&'a P), + /// Set a parameter to a new normalized value. This needs to be surrounded by a matching + /// `BeginSetParameter` and `EndSetParameter`. + SetParameter(&'a P, P::Plain), + /// Set a parameter to a new normalized value. This needs to be surrounded by a matching + /// `BeginSetParameter` and `EndSetParameter`. + SetParameterNormalized(&'a P, f32), + /// Reset a parameter to its default value. This needs to be surrounded by a matching + /// `BeginSetParameter` and `EndSetParameter`. + ResetParameter(&'a P), + /// End an automation gesture for a parameter. + EndSetParameter(&'a P), +} + +/// The same as [`ParamEvent`], but type erased. +#[derive(Debug, Clone, Copy)] +pub enum NormalizedParamEvent { /// 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 @@ -36,19 +58,49 @@ pub(crate) struct ParamModel { impl Model for ParamModel { fn event(&mut self, _cx: &mut vizia::Context, event: &mut vizia::Event) { if let Some(param_event) = event.message.downcast() { + // `ParamEvent` gets downcast into `NormalizedParamEvent` by the `Message` + // implementation below match *param_event { - ParamEvent::BeginSetParameter(p) => unsafe { + NormalizedParamEvent::BeginSetParameter(p) => unsafe { self.context.raw_begin_set_parameter(p) }, - ParamEvent::SetParameterNormalized(p, v) => unsafe { + NormalizedParamEvent::SetParameterNormalized(p, v) => unsafe { self.context.raw_set_parameter_normalized(p, v) }, - ParamEvent::ResetParameter(p) => unsafe { + NormalizedParamEvent::ResetParameter(p) => unsafe { let default_value = self.context.raw_default_normalized_param_value(p); self.context.raw_set_parameter_normalized(p, default_value); }, - ParamEvent::EndSetParameter(p) => unsafe { self.context.raw_end_set_parameter(p) }, + NormalizedParamEvent::EndSetParameter(p) => unsafe { + self.context.raw_end_set_parameter(p) + }, } } } } + +impl From> for NormalizedParamEvent { + fn from(event: ParamEvent<'_, P>) -> Self { + match event { + ParamEvent::BeginSetParameter(p) => NormalizedParamEvent::BeginSetParameter(p.as_ptr()), + ParamEvent::SetParameter(p, v) => { + NormalizedParamEvent::SetParameterNormalized(p.as_ptr(), p.preview_normalized(v)) + } + ParamEvent::SetParameterNormalized(p, v) => { + NormalizedParamEvent::SetParameterNormalized(p.as_ptr(), v) + } + ParamEvent::ResetParameter(p) => NormalizedParamEvent::ResetParameter(p.as_ptr()), + ParamEvent::EndSetParameter(p) => NormalizedParamEvent::EndSetParameter(p.as_ptr()), + } + } +} + +impl ParamEvent<'_, P> { + /// Convert this event into a type erased version of itself that can be emitted through + /// [`Context::emit()`][vizia::Context::emit()]. + /// + /// TODO: Think of a better, clearer term for this + pub fn upcast(self) -> NormalizedParamEvent { + self.into() + } +}