Wrap Diopser safe mode boolean in a struct
This struct will also be used to limit the parameter ranges later.
This commit is contained in:
parent
9a77bd2918
commit
4eb7614ee7
|
@ -20,7 +20,6 @@ use nih_plug::prelude::{Editor, Plugin};
|
|||
use nih_plug_vizia::vizia::prelude::*;
|
||||
use nih_plug_vizia::widgets::*;
|
||||
use nih_plug_vizia::{assets, create_vizia_editor, ViziaState, ViziaTheming};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use self::button::SafeModeButton;
|
||||
|
@ -30,8 +29,11 @@ use crate::Diopser;
|
|||
|
||||
mod analyzer;
|
||||
mod button;
|
||||
mod safe_mode;
|
||||
mod xy_pad;
|
||||
|
||||
pub use safe_mode::SafeModeClamper;
|
||||
|
||||
const EDITOR_WIDTH: u32 = 600;
|
||||
const EDITOR_HEIGHT: u32 = 490;
|
||||
|
||||
|
@ -49,8 +51,7 @@ pub(crate) struct Data {
|
|||
pub(crate) spectrum: Arc<Mutex<SpectrumOutput>>,
|
||||
/// Whether the safe mode button is enabled. The number of filter stages is capped at 40 while
|
||||
/// this is active.
|
||||
/// TODO: Actually hook up safe mode
|
||||
pub(crate) safe_mode: Arc<AtomicBool>,
|
||||
pub(crate) safe_mode_clamper: SafeModeClamper,
|
||||
}
|
||||
|
||||
impl Model for Data {}
|
||||
|
@ -106,7 +107,7 @@ fn top_bar(cx: &mut Context) {
|
|||
.with_label("Automation Precision")
|
||||
.id("automation-precision");
|
||||
|
||||
SafeModeButton::new(cx, Data::safe_mode, "Safe mode").left(Pixels(10.0));
|
||||
SafeModeButton::new(cx, Data::safe_mode_clamper, "Safe mode").left(Pixels(10.0));
|
||||
|
||||
ParamButton::new(cx, Data::params, |params| ¶ms.bypass)
|
||||
.for_bypass()
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use nih_plug_vizia::vizia::prelude::*;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A custom toggleable button coupled to an `Arc<AtomicBool`. Otherwise this is very similar to the
|
||||
/// param button.
|
||||
use super::SafeModeClamper;
|
||||
|
||||
/// A custom toggleable button that toggles safe mode whenever it is Alt+clicked. Otherwise this is
|
||||
/// very similar to the param button.
|
||||
#[derive(Lens)]
|
||||
pub struct SafeModeButton<L: Lens<Target = Arc<AtomicBool>>> {
|
||||
pub struct SafeModeButton<L: Lens<Target = SafeModeClamper>> {
|
||||
lens: L,
|
||||
|
||||
/// The number of (fractional) scrolled lines that have not yet been turned into parameter
|
||||
|
@ -29,8 +29,8 @@ pub struct SafeModeButton<L: Lens<Target = Arc<AtomicBool>>> {
|
|||
scrolled_lines: f32,
|
||||
}
|
||||
|
||||
impl<L: Lens<Target = Arc<AtomicBool>>> SafeModeButton<L> {
|
||||
/// Creates a new button bound to the `Arc<AtomicBool>`.
|
||||
impl<L: Lens<Target = SafeModeClamper>> SafeModeButton<L> {
|
||||
/// Creates a new button bound to the [`SafeModeClamper`].
|
||||
pub fn new<T>(cx: &mut Context, lens: L, label: impl Res<T>) -> Handle<Self>
|
||||
where
|
||||
T: ToString,
|
||||
|
@ -42,13 +42,13 @@ impl<L: Lens<Target = Arc<AtomicBool>>> SafeModeButton<L> {
|
|||
.build(cx, move |cx| {
|
||||
Label::new(cx, label);
|
||||
})
|
||||
.checked(lens.map(|v| v.load(Ordering::Relaxed)))
|
||||
.checked(lens.map(|v| v.status()))
|
||||
// We'll pretend this is a param-button, so this class is used for assigning a unique color
|
||||
.class("safe-mode")
|
||||
}
|
||||
}
|
||||
|
||||
impl<L: Lens<Target = Arc<AtomicBool>>> View for SafeModeButton<L> {
|
||||
impl<L: Lens<Target = SafeModeClamper>> View for SafeModeButton<L> {
|
||||
fn element(&self) -> Option<&'static str> {
|
||||
// Reuse the styling from param-button
|
||||
Some("param-button")
|
||||
|
@ -60,9 +60,10 @@ impl<L: Lens<Target = Arc<AtomicBool>>> View for SafeModeButton<L> {
|
|||
WindowEvent::MouseDown(MouseButton::Left)
|
||||
| WindowEvent::MouseDoubleClick(MouseButton::Left)
|
||||
| WindowEvent::MouseTripleClick(MouseButton::Left) => {
|
||||
// We can just unconditionally toggle the boolean here
|
||||
let atomic = self.lens.get(cx);
|
||||
atomic.fetch_xor(true, Ordering::AcqRel);
|
||||
// We can just unconditionally toggle the boolean here. When safe mode is enabled
|
||||
// this immediately clamps the affected parameters to their new range.
|
||||
let safe_mode_clamper = self.lens.get(cx);
|
||||
safe_mode_clamper.toggle(cx);
|
||||
|
||||
meta.consume();
|
||||
}
|
||||
|
@ -70,13 +71,13 @@ impl<L: Lens<Target = Arc<AtomicBool>>> View for SafeModeButton<L> {
|
|||
self.scrolled_lines += scroll_y;
|
||||
|
||||
if self.scrolled_lines.abs() >= 1.0 {
|
||||
let atomic = self.lens.get(cx);
|
||||
let safe_mode_clamper = self.lens.get(cx);
|
||||
|
||||
if self.scrolled_lines >= 1.0 {
|
||||
atomic.store(true, Ordering::SeqCst);
|
||||
safe_mode_clamper.enable(cx);
|
||||
self.scrolled_lines -= 1.0;
|
||||
} else {
|
||||
atomic.store(false, Ordering::SeqCst);
|
||||
safe_mode_clamper.disable(cx);
|
||||
self.scrolled_lines += 1.0;
|
||||
}
|
||||
}
|
||||
|
|
48
plugins/diopser/src/editor/safe_mode.rs
Normal file
48
plugins/diopser/src/editor/safe_mode.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
//! Utilities for Diopser's safe-mode mechanism.
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use nih_plug_vizia::vizia::prelude::EventContext;
|
||||
|
||||
use crate::params::DiopserParams;
|
||||
|
||||
/// Restricts the ranges of several parameters when enabled. This makes it more difficult to
|
||||
/// generate load resonances with Diopser's default settings.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SafeModeClamper {
|
||||
/// Whether the safe mode toggle has been enabled.
|
||||
enabled: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl SafeModeClamper {
|
||||
pub fn new(params: Arc<DiopserParams>) -> Self {
|
||||
Self {
|
||||
enabled: params.safe_mode.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the current status of the safe mode swtich.
|
||||
pub fn status(&self) -> bool {
|
||||
self.enabled.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Enable or disable safe mode. Enabling safe mode immediately clamps the parameters to their
|
||||
/// new restricted ranges.
|
||||
pub fn toggle(&self, cx: &mut EventContext) {
|
||||
// TODO: Restrict the parameter ranges when the button is enabled
|
||||
self.enabled.fetch_xor(true, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Enable safe mode. Enabling safe mode immediately clamps the parameters to their new
|
||||
/// restricted ranges.
|
||||
pub fn enable(&self, cx: &mut EventContext) {
|
||||
// TODO: Restrict the parameter ranges when the button is enabled
|
||||
self.enabled.store(true, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Disable safe mode.
|
||||
pub fn disable(&self, cx: &mut EventContext) {
|
||||
self.enabled.store(false, Ordering::Relaxed);
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
compile_error!("Compiling without SIMD support is currently not supported");
|
||||
|
||||
use atomic_float::AtomicF32;
|
||||
use editor::SafeModeClamper;
|
||||
use nih_plug::prelude::*;
|
||||
use std::simd::f32x2;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
@ -130,7 +131,7 @@ impl Plugin for Diopser {
|
|||
|
||||
sample_rate: self.sample_rate.clone(),
|
||||
spectrum: self.spectrum_output.clone(),
|
||||
safe_mode: self.params.safe_mode.clone(),
|
||||
safe_mode_clamper: SafeModeClamper::new(self.params.clone()),
|
||||
},
|
||||
self.params.editor_state.clone(),
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue