diff --git a/src/editor.rs b/src/editor.rs index 8b7a649..0dc560a 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -13,7 +13,7 @@ use nih_plug_vizia::{ use crate::{ util, AtomicBoolArray, AtomicByteArray, Del2Params, DelayData, DelayDataOutput, - LastPlayedNotes, LEARNING, LOCK_PATTERN, MUTE_IN, MUTE_OUT, NO_LEARNED_NOTE, RESET_PATTERN, + LastPlayedNotes, LEARNING, LOCK_TAPS, MUTE_IN, MUTE_OUT, NO_LEARNED_NOTE, RESET_TAPS, }; #[derive(Lens, Clone)] @@ -118,7 +118,7 @@ pub fn create(editor_data: Data, editor_state: Arc) -> Option) -> Option) -> Option) -> Optioncut").class("slider-label"); + Label::new(cx, "vel>cut").class("slider-label"); ParamSlider::new(cx, Data::params, |params| { ¶ms.taps.velocity_to_cutoff_amount }) @@ -211,7 +211,7 @@ pub fn create(editor_data: Data, editor_state: Arc) -> Optioncut").class("slider-label"); + Label::new(cx, "note>cut").class("slider-label"); ParamSlider::new(cx, Data::params, |params| { ¶ms.taps.note_to_cutoff_amount }) @@ -296,7 +296,7 @@ pub fn create(editor_data: Data, editor_state: Arc) -> Option f32 { let max_delay_time = if delay_data.current_tap > 0 { delay_data.delay_times[delay_data.current_tap - 1] @@ -403,7 +403,7 @@ impl DelayGraph { 0 }; ((max_delay_time as f32 + delay_data.max_tap_samples as f32) - / (rect_width - border_width - path_line_width * 0.5)) + / (rect_width - border_width - outline_width * 0.5)) .recip() } @@ -431,10 +431,7 @@ impl DelayGraph { path.line_to(bounds.x + x_offset, end_y); } - canvas.stroke_path( - &path, - &vg::Paint::color(border_color).with_line_width(border_width), - ); + canvas.stroke_path(&path, &vg::Paint::color(border_color).with_line_width(0.7)); } fn draw_background( @@ -536,20 +533,23 @@ impl DelayGraph { }; let diamond_size = line_width * 2.0; // Width and height of a diamond - let available_height = bounds.h - border_width - 2.0 * diamond_size; + + // Calculate available height with margins as 3 times the outline width + let margin = 3.0 * line_width; + let available_height = bounds.h - 2.0 * (margin + diamond_size + border_width); for i in 0..delay_data.current_tap { let x_offset = delay_data.delay_times[i] as f32 * scaling_factor + border_width * 0.5; - // Adjust note height to scale within bounds + // Adjust note height to scale within bounds considering margins let normalized_note = if max_note_value != min_note_value { (delay_data.notes[i] as f32 - min_note_value) / (max_note_value - min_note_value) } else { delay_data.notes[i] as f32 / 127.0 }; - // Use scaling to ensure the diamond fits within the available height - let note_height = diamond_size + (1.0 - normalized_note) * available_height; + // Scale the normalized note to fit within available height + let note_height = margin + diamond_size + (1.0 - normalized_note) * available_height; let diamond_center_x = bounds.x + x_offset; let diamond_center_y = bounds.y + note_height; @@ -705,12 +705,18 @@ impl ActionTrigger { border_color: vg::Color, border_width: f32, ) { + // Adjust bounds for borders + let x = bounds.x + border_width * 0.5; + let y = bounds.y + border_width * 0.5; + let w = bounds.w - border_width; + let h = bounds.h - border_width; + // Drawing the background rectangle let mut path = vg::Path::new(); - path.rect(bounds.x, bounds.y, bounds.w, bounds.h); + path.rect(x, y, w, h); path.close(); - // Determine the paint color based on the learning state + // Determine the paint color based on the state let paint = if self.is_learning() { vg::Paint::color(border_color) } else if self.is_playing() { @@ -724,7 +730,7 @@ impl ActionTrigger { // Drawing the border around the rectangle let mut path = vg::Path::new(); - path.rect(bounds.x, bounds.y, bounds.w, bounds.h); + path.rect(x, y, w, h); path.close(); canvas.stroke_path( @@ -763,7 +769,7 @@ impl View for ActionTrigger { let outline_color: vg::Color = draw_context.outline_color().into(); let selection_color: vg::Color = draw_context.selection_color().into(); let border_width = draw_context.border_width(); - // let path_line_width = draw_context.outline_width(); + // let outline_width = draw_context.outline_width(); self.draw_background( canvas, diff --git a/src/lib.rs b/src/lib.rs index 1eb35cb..2f9d8d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,8 +48,8 @@ const LEARNING: u8 = 129; // should be 0..7 because of AtomicByteArray size const MUTE_IN: usize = 0; const MUTE_OUT: usize = 1; -const RESET_PATTERN: usize = 2; -const LOCK_PATTERN: usize = 3; +const RESET_TAPS: usize = 2; +const LOCK_TAPS: usize = 3; struct Del2 { params: Arc, @@ -166,8 +166,8 @@ impl GlobalParams { factor: FloatRange::skew_factor(-2.0), }, ) - .with_step_size(0.1) - .with_unit(" ms"), + .with_value_to_string(Del2::v2s_f32_ms_then_s(1)) + .with_string_to_value(Del2::s2v_f32_ms_then_s()), } } } @@ -616,25 +616,25 @@ impl Del2 { self.last_played_notes.note_on(note); - if self.is_playing_action(LOCK_PATTERN) { - self.enabled_actions.toggle(LOCK_PATTERN); + if self.is_playing_action(LOCK_TAPS) { + self.enabled_actions.toggle(LOCK_TAPS); self.last_played_notes - .note_off(self.learned_notes.load(LOCK_PATTERN)); + .note_off(self.learned_notes.load(LOCK_TAPS)); } let mut should_record_tap = is_delay_note && is_tap_slot_available - && !self.enabled_actions.load(LOCK_PATTERN) + && !self.enabled_actions.load(LOCK_TAPS) && !is_learning; match self.counting_state { CountingState::TimeOut => { if is_delay_note && !is_learning - && !self.enabled_actions.load(LOCK_PATTERN) + && !self.enabled_actions.load(LOCK_TAPS) { // If in TimeOut state, reset and start new counting phase - self.reset_pattern(timing); + self.reset_taps(timing); } } CountingState::CountingInBuffer => { @@ -725,8 +725,8 @@ impl Del2 { self.enabled_actions.store(MUTE_OUT, true); } } - if self.is_playing_action(RESET_PATTERN) { - self.reset_pattern(timing); + if self.is_playing_action(RESET_TAPS) { + self.reset_taps(timing); } } // Handling NoteOff events @@ -740,7 +740,7 @@ impl Del2 { } } - fn reset_pattern(&mut self, timing: u32) { + fn reset_taps(&mut self, timing: u32) { self.mute_all_outs(true); self.enabled_actions.store(MUTE_IN, false); self.enabled_actions.store(MUTE_OUT, false); @@ -1075,20 +1075,32 @@ impl Del2 { } } - pub fn is_playing_action(&self, index: usize) -> bool { + fn is_playing_action(&self, index: usize) -> bool { self.last_played_notes .is_playing(self.learned_notes.load(index)) } - pub fn _no_learned_note_are_playing(&self) -> bool { - for i in 0..MAX_LEARNED_NOTES { - if self - .last_played_notes - .is_playing(self.learned_notes.load(i)) - { - return false; + + fn v2s_f32_ms_then_s(digits: usize) -> Arc String + Send + Sync> { + Arc::new(move |value| { + if value < 1000.0 { + format!("{value:.digits$} ms") + } else { + format!("{:.digits$} s", value / 1000.0, digits = digits.max(1)) } - } - true + }) + } + + fn s2v_f32_ms_then_s() -> Arc Option + Send + Sync> { + Arc::new(move |string| { + let string = string.trim().to_lowercase(); + if let Some(ms_value_str) = string.strip_suffix("ms").or(string.strip_suffix(" ms")) { + return ms_value_str.trim().parse::().ok(); + } + if let Some(s_value_str) = string.strip_suffix("s").or(string.strip_suffix(" s")) { + return s_value_str.trim().parse::().ok().map(|s| s * 1000.0); + } + string.parse::().ok() + }) } } diff --git a/src/style.css b/src/style.css index 9929597..0f21b22 100644 --- a/src/style.css +++ b/src/style.css @@ -58,16 +58,10 @@ param-slider .value-entry { .plugin-name { color: #fabdf0; font-size: 42; - top: 12px; + top: 9px; right: 18px; } -.meters_and_name { - top: 14px; - right: 9px; - height: 80px; -} - .global-title { font-size: 30; /* // This should align nicely with the right edge of the slider */ @@ -111,7 +105,7 @@ param-slider .value-entry { delay-graph { top: 9px; right: 9px; - border-width: 2px; + border-width: 1px; outline-width: 5px; border-color: #4e4e4e; outline-color: #5879af; @@ -133,7 +127,7 @@ action-trigger { .action-name { right: 9px; top: 1s; - bottom: 3px; + bottom: 4px; } generic-ui { child-left: 0px; @@ -178,12 +172,19 @@ generic-ui .label { bottom: 1s; } +.peak-meter-group { + height: 73px; + right: 9px; + top: 9px; + bottom: 0px; +} + peak-meter { - height: 30px; width: 584px; + height: 18px; color: #e0ce91; left: 0px; - bottom: 6px; + bottom: 0px; } peak-meter .bar { @@ -207,8 +208,8 @@ peak-meter .ticks__label { } .meter-label { child-left: 1s; - right: 3px; - bottom: 24px; + right: 6px; + bottom: 23px; font-size: 15; width: 40px; }