diff --git a/plugins/dfpworm/src/dfpwm.rs b/plugins/dfpworm/src/dfpwm.rs index 9965b9c..65232af 100644 --- a/plugins/dfpworm/src/dfpwm.rs +++ b/plugins/dfpworm/src/dfpwm.rs @@ -1,7 +1,7 @@ -pub const DEFAULT_RESPONSE_INCREASE: f32 = 7.0 / 127.0; +pub const DEFAULT_RESPONSE_INCREASE: f32 = 7.0 / 128.0; pub const DEFAULT_RESPONSE_DECREASE: f32 = 20.0 / 128.0; -const NUDGE: f32 = 1.0 / 128.0; +pub const NUDGE: f32 = 1.0 / 128.0; pub struct Context { pub response_increase: f32, diff --git a/plugins/dfpworm/src/editor.rs b/plugins/dfpworm/src/editor.rs index 10235f7..66f8ba7 100644 --- a/plugins/dfpworm/src/editor.rs +++ b/plugins/dfpworm/src/editor.rs @@ -1,4 +1,6 @@ use nih_plug::editor::Editor; +use nih_plug_vizia::vizia::image::DynamicImage; +use nih_plug_vizia::vizia::image::codecs::png::PngDecoder; use nih_plug_vizia::vizia::prelude::*; use nih_plug_vizia::{ViziaState, assets, create_vizia_editor, widgets::*}; use std::sync::Arc; @@ -13,7 +15,7 @@ struct Data { impl Model for Data {} pub(crate) fn default_state() -> Arc { - ViziaState::new(|| (200, 150)) + ViziaState::new(|| (216, 240)) } pub(crate) fn create( @@ -24,35 +26,64 @@ pub(crate) fn create( editor_state, nih_plug_vizia::ViziaTheming::Custom, move |cx, _| { - assets::register_noto_sans_light(cx); - assets::register_noto_sans_thin(cx); + assets::register_noto_sans_bold(cx); Data { params: params.clone(), } .build(cx); + // load images + // TODO: find out if this should be moved out of this function for perf reasons? + load_image(cx, "logo", &include_bytes!("resources/logo.png")[..]); + load_image( + cx, + "background", + &include_bytes!("resources/background.png")[..], + ); + load_image( + cx, + "aggression", + &include_bytes!("resources/aggression.png")[..], + ); + load_image( + cx, + "relaxation", + &include_bytes!("resources/relaxation.png")[..], + ); + + // apply stylesheet + cx.add_stylesheet(include_str!("resources/style.css")) + .expect("Failed to load stylesheet."); + + // build the ui VStack::new(cx, |cx| { - Label::new(cx, "Dirty Frying Pan Worm") - .font_family(vec![FamilyOwned::Name(String::from(assets::NOTO_SANS))]) - .font_weight(FontWeightKeyword::Thin) - .font_size(30.0) - .height(Pixels(60.0)) - .text_align(TextAlign::Center) - .child_top(Stretch(1.0)) - .child_bottom(Pixels(0.0)); + Element::new(cx).class("logo"); // response increase - Label::new(cx, "Aggression"); - ParamSlider::new(cx, Data::params, |params| ¶ms.response_increase); + Element::new(cx) + .class("param-header") + .background_image(vec![BackgroundImage::from("url('aggression')")]); + ParamSlider::new(cx, Data::params, |params| ¶ms.response_increase) + .class("param-slider"); // response decrease - Label::new(cx, "Regression").top(Pixels(10.0)); - ParamSlider::new(cx, Data::params, |params| ¶ms.response_decrease); + Element::new(cx) + .class("param-header") + .background_image(vec![BackgroundImage::from("url('relaxation')")]); + ParamSlider::new(cx, Data::params, |params| ¶ms.response_decrease) + .class("param-slider"); }) - .row_between(Pixels(0.0)) - .child_left(Stretch(1.0)) - .child_right(Stretch(1.0)); + .class("root"); }, ) } + +fn load_image(cx: &mut Context, name: &str, data: &[u8]) { + cx.load_image( + name, + DynamicImage::from_decoder(PngDecoder::new(data).expect("Failed to load image.")) + .expect("Failed to load image."), + ImageRetentionPolicy::Forever, + ); +} diff --git a/plugins/dfpworm/src/lib.rs b/plugins/dfpworm/src/lib.rs index 21be160..c4b766a 100644 --- a/plugins/dfpworm/src/lib.rs +++ b/plugins/dfpworm/src/lib.rs @@ -44,17 +44,32 @@ impl Default for WormParams { "Response Increase", dfpwm::DEFAULT_RESPONSE_INCREASE, FloatRange::Linear { min: 0.0, max: 1.0 }, - ), + ) + .with_step_size(dfpwm::NUDGE) + .with_value_to_string(v2s_f32_scaled_int(dfpwm::NUDGE)) + .with_string_to_value(s2v_f32_scaled_int(dfpwm::NUDGE)), response_decrease: FloatParam::new( "Response Decrease", dfpwm::DEFAULT_RESPONSE_DECREASE, FloatRange::Linear { min: 0.0, max: 1.0 }, - ), + ) + .with_step_size(dfpwm::NUDGE) + .with_value_to_string(v2s_f32_scaled_int(dfpwm::NUDGE)) + .with_string_to_value(s2v_f32_scaled_int(dfpwm::NUDGE)), } } } +fn v2s_f32_scaled_int(step: f32) -> Arc String + Send + Sync> { + let scale = step.recip(); + Arc::new(move |value| format!("{}", (value * scale).floor())) +} + +pub fn s2v_f32_scaled_int(step: f32) -> Arc Option + Send + Sync> { + Arc::new(move |string| string.parse().ok().map(|x: f32| x * step)) +} + impl Plugin for Worm { const NAME: &'static str = "Dirty Frying Pan Worm"; diff --git a/plugins/dfpworm/src/resources/aggression.png b/plugins/dfpworm/src/resources/aggression.png new file mode 100644 index 0000000..c25d58f Binary files /dev/null and b/plugins/dfpworm/src/resources/aggression.png differ diff --git a/plugins/dfpworm/src/resources/background.png b/plugins/dfpworm/src/resources/background.png new file mode 100644 index 0000000..0027069 Binary files /dev/null and b/plugins/dfpworm/src/resources/background.png differ diff --git a/plugins/dfpworm/src/resources/logo.png b/plugins/dfpworm/src/resources/logo.png index 9f0f1bd..2ac5db9 100644 Binary files a/plugins/dfpworm/src/resources/logo.png and b/plugins/dfpworm/src/resources/logo.png differ diff --git a/plugins/dfpworm/src/resources/relaxation.png b/plugins/dfpworm/src/resources/relaxation.png new file mode 100644 index 0000000..cc0a162 Binary files /dev/null and b/plugins/dfpworm/src/resources/relaxation.png differ diff --git a/plugins/dfpworm/src/resources/style.css b/plugins/dfpworm/src/resources/style.css new file mode 100644 index 0000000..bb486b7 --- /dev/null +++ b/plugins/dfpworm/src/resources/style.css @@ -0,0 +1,31 @@ +.root { + background-image: url("background"); +} + +.logo { + background-image: url("logo"); + width: 200px; + height: 64px; + top: 8px; + left: 1s; + right: 1s; +} + +.param-header { + width: 160px; + height: 32px; + top: 12px; + left: 1s; + right: 1s; +} + +.param-slider { + width: 180px; + left: 1s; + right: 1s; +} + +.param-slider .value { + color: #22dd5f; + font-weight: bold; +} \ No newline at end of file