From 6fc733e029b818c4a79f3654883749e897b63d42 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Mon, 31 Jan 2022 21:02:47 +0100 Subject: [PATCH] Add callbacks for parameter changes --- plugins/gain/src/lib.rs | 6 ++++++ src/params.rs | 26 +++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/plugins/gain/src/lib.rs b/plugins/gain/src/lib.rs index e87b06d8..7da85b83 100644 --- a/plugins/gain/src/lib.rs +++ b/plugins/gain/src/lib.rs @@ -55,6 +55,12 @@ impl Default for GainParams { Self { gain: FloatParam { value: 0.0, + value_changed: None, + // If, for instance, updating this parameter would require other parts of the + // plugin's internal state to be updated other values to also be updated, then you + // can use a callback like this, where `requires_updates` is an `Arc` + // that's also stored on the parameters struct: + // value_changed: Some(Arc::new(move |_new| { requires_update.store(true, Ordering::Release); })), range: Range::Linear { min: -30.0, max: 30.0, diff --git a/src/params.rs b/src/params.rs index 4a2dcd57..b94b54b9 100644 --- a/src/params.rs +++ b/src/params.rs @@ -39,7 +39,7 @@ pub enum Range { /// A normalizable range for type `T`, where `self` is expected to be a type `R`. Higher kinded /// types would have made this trait definition a lot clearer. trait NormalizebleRange { - /// Normalize an unnormalized value. Will be clamped to the bounds of the range if the + /// Normalize a plain, unnormalized value. Will be clamped to the bounds of the range if the /// normalized value exceeds `[0, 1]`. fn normalize(&self, plain: T) -> f32; @@ -51,11 +51,16 @@ trait NormalizebleRange { /// A numerical parameter that's stored unnormalized. The range is used for the normalization /// process. pub struct PlainParam { - /// The field's current, normalized value. Should be initialized with the default value. Storing - /// parameter values like this instead of in a single contiguous array is bad for cache + /// The field's current plain, unnormalized value. Should be initialized with the default value. + /// Storing parameter values like this instead of in a single contiguous array is bad for cache /// locality, but it does allow for a much nicer declarative API. pub value: T, + /// Optional callback for listening to value changes. The argument passed to this function is + /// the parameter's new **plain** value. This should not do anything expensive as it may be + /// called multiple times in rapid succession. + pub value_changed: Option () + Send + Sync>>, + /// The distribution of the parameter's values. pub range: Range, /// The parameter's human readable display name. @@ -75,6 +80,11 @@ pub struct BoolParam { /// The field's current, normalized value. Should be initialized with the default value. pub value: bool, + /// Optional callback for listening to value changes. The argument passed to this function is + /// the parameter's new value. This should not do anything expensive as it may be called + /// multiple times in rapid succession. + pub value_changed: Option () + Send + Sync>>, + /// The parameter's human readable display name. pub name: &'static str, /// Optional custom conversion function from a boolean value to a string. @@ -147,6 +157,9 @@ macro_rules! impl_plainparam { fn set_plain_value(&mut self, plain: Self::Plain) { self.value = plain; + if let Some(f) = &self.value_changed { + f(plain); + } } fn normalized_value(&self) -> f32 { @@ -154,7 +167,7 @@ macro_rules! impl_plainparam { } fn set_normalized_value(&mut self, normalized: f32) { - self.value = self.range.unnormalize(normalized); + self.set_plain_value(self.range.unnormalize(normalized)); } fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String { @@ -211,6 +224,9 @@ impl Param for BoolParam { fn set_plain_value(&mut self, plain: Self::Plain) { self.value = plain; + if let Some(f) = &self.value_changed { + f(plain); + } } fn normalized_value(&self) -> f32 { @@ -222,7 +238,7 @@ impl Param for BoolParam { } fn set_normalized_value(&mut self, normalized: f32) { - self.value = normalized > 0.5; + self.set_plain_value(normalized > 0.5); } fn normalized_value_to_string(&self, normalized: f32, _include_unit: bool) -> String {