1
0
Fork 0

Add finer step sizes to parameters

This commit is contained in:
Robbert van der Helm 2022-11-08 22:03:26 +01:00
parent 8885713ea1
commit e583b8e777
10 changed files with 58 additions and 40 deletions

View file

@ -6,6 +6,13 @@ new and what's changed, this document lists all breaking changes in reverse
chronological order. If a new feature did not require any changes to existing chronological order. If a new feature did not require any changes to existing
code then it will not be listed here. code then it will not be listed here.
## [2022-11-08]
- The `Param::{next_previous}{_step,_normalized_step}()` functions now take an
additional boolean argument to indicate that the range must be finer. This is
used for floating point parameters to chop the range up into smaller segments
when using Shift+scroll.
## [2022-11-07] ## [2022-11-07]
- `Param::plain_value()` and `Param::normalized_value()` have been renamed to - `Param::plain_value()` and `Param::normalized_value()` have been renamed to

View file

@ -219,8 +219,8 @@ impl ParamWidgetBase {
param_ptr_forward!(pub fn default_plain_value(&self) -> f32); param_ptr_forward!(pub fn default_plain_value(&self) -> f32);
param_ptr_forward!(pub fn default_normalized_value(&self) -> f32); param_ptr_forward!(pub fn default_normalized_value(&self) -> f32);
param_ptr_forward!(pub fn step_count(&self) -> Option<usize>); param_ptr_forward!(pub fn step_count(&self) -> Option<usize>);
param_ptr_forward!(pub fn previous_normalized_step(&self, from: f32) -> f32); param_ptr_forward!(pub fn previous_normalized_step(&self, from: f32, finer: bool) -> f32);
param_ptr_forward!(pub fn next_normalized_step(&self, from: f32) -> f32); param_ptr_forward!(pub fn next_normalized_step(&self, from: f32, finer: bool) -> f32);
param_ptr_forward!(pub fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String); param_ptr_forward!(pub fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String);
param_ptr_forward!(pub fn string_to_normalized_value(&self, string: &str) -> Option<f32>); param_ptr_forward!(pub fn string_to_normalized_value(&self, string: &str) -> Option<f32>);
param_ptr_forward!(pub fn preview_normalized(&self, plain: f32) -> f32); param_ptr_forward!(pub fn preview_normalized(&self, plain: f32) -> f32);

View file

@ -364,8 +364,8 @@ impl ParamSlider {
(previous_step, discrete_values.recip()) (previous_step, discrete_values.recip())
} }
ParamSliderStyle::CurrentStep { .. } | ParamSliderStyle::CurrentStepLabeled { .. } => { ParamSliderStyle::CurrentStep { .. } | ParamSliderStyle::CurrentStepLabeled { .. } => {
let previous_step = param.previous_normalized_step(current_value); let previous_step = param.previous_normalized_step(current_value, false);
let next_step = param.next_normalized_step(current_value); let next_step = param.next_normalized_step(current_value, false);
( (
(previous_step + current_value) / 2.0, (previous_step + current_value) / 2.0,
@ -570,13 +570,15 @@ impl View for ParamSlider {
let mut current_value = self.param_base.unmodulated_normalized_value(); let mut current_value = self.param_base.unmodulated_normalized_value();
while self.scrolled_lines >= 1.0 { while self.scrolled_lines >= 1.0 {
current_value = self.param_base.next_normalized_step(current_value); current_value = self.param_base.next_normalized_step(current_value, false);
self.param_base.set_normalized_value(cx, current_value); self.param_base.set_normalized_value(cx, current_value);
self.scrolled_lines -= 1.0; self.scrolled_lines -= 1.0;
} }
while self.scrolled_lines <= -1.0 { while self.scrolled_lines <= -1.0 {
current_value = self.param_base.previous_normalized_step(current_value); current_value = self
.param_base
.previous_normalized_step(current_value, false);
self.param_base.set_normalized_value(cx, current_value); self.param_base.set_normalized_value(cx, current_value);
self.scrolled_lines += 1.0; self.scrolled_lines += 1.0;
} }

View file

@ -120,24 +120,28 @@ pub trait Param: Display {
/// `from` if the value is at the start of its range. This is mainly used for scroll wheel /// `from` if the value is at the start of its range. This is mainly used for scroll wheel
/// interaction in plugin GUIs. When the parameter is not discrete then a step should cover one /// interaction in plugin GUIs. When the parameter is not discrete then a step should cover one
/// hundredth of the normalized range instead. /// hundredth of the normalized range instead.
fn previous_step(&self, from: Self::Plain) -> Self::Plain; ///
/// If `finer` is true, then the step size should be decreased if the parameter is continuous.
fn previous_step(&self, from: Self::Plain, finer: bool) -> Self::Plain;
/// Returns the next step from a specific value for this parameter. This can be the same as /// Returns the next step from a specific value for this parameter. This can be the same as
/// `from` if the value is at the end of its range. This is mainly used for scroll wheel /// `from` if the value is at the end of its range. This is mainly used for scroll wheel
/// interaction in plugin GUIs. When the parameter is not discrete then a step should cover one /// interaction in plugin GUIs. When the parameter is not discrete then a step should cover one
/// hundredth of the normalized range instead. /// hundredth of the normalized range instead.
fn next_step(&self, from: Self::Plain) -> Self::Plain; ///
/// If `finer` is true, then the step size should be decreased if the parameter is continuous.
fn next_step(&self, from: Self::Plain, finer: bool) -> Self::Plain;
/// The same as [`previous_step()`][Self::previous_step()], but for normalized values. This is /// The same as [`previous_step()`][Self::previous_step()], but for normalized values. This is
/// mostly useful for GUI widgets. /// mostly useful for GUI widgets.
fn previous_normalized_step(&self, from: f32) -> f32 { fn previous_normalized_step(&self, from: f32, finer: bool) -> f32 {
self.preview_normalized(self.previous_step(self.preview_plain(from))) self.preview_normalized(self.previous_step(self.preview_plain(from), finer))
} }
/// The same as [`next_step()`][Self::next_step()], but for normalized values. This is mostly /// The same as [`next_step()`][Self::next_step()], but for normalized values. This is mostly
/// useful for GUI widgets. /// useful for GUI widgets.
fn next_normalized_step(&self, from: f32) -> f32 { fn next_normalized_step(&self, from: f32, finer: bool) -> f32 {
self.preview_normalized(self.next_step(self.preview_plain(from))) self.preview_normalized(self.next_step(self.preview_plain(from), finer))
} }
/// Get the string representation for a normalized value. Used as part of the wrappers. Most /// Get the string representation for a normalized value. Used as part of the wrappers. Most

View file

@ -105,11 +105,11 @@ impl Param for BoolParam {
Some(1) Some(1)
} }
fn previous_step(&self, _from: Self::Plain) -> Self::Plain { fn previous_step(&self, _from: Self::Plain, _finer: bool) -> Self::Plain {
false false
} }
fn next_step(&self, _from: Self::Plain) -> Self::Plain { fn next_step(&self, _from: Self::Plain, _finer: bool) -> Self::Plain {
true true
} }

View file

@ -154,12 +154,12 @@ impl<T: Enum + PartialEq> Param for EnumParam<T> {
self.inner.step_count() self.inner.step_count()
} }
fn previous_step(&self, from: Self::Plain) -> Self::Plain { fn previous_step(&self, from: Self::Plain, finer: bool) -> Self::Plain {
T::from_index(self.inner.previous_step(T::to_index(from) as i32) as usize) T::from_index(self.inner.previous_step(T::to_index(from) as i32, finer) as usize)
} }
fn next_step(&self, from: Self::Plain) -> Self::Plain { fn next_step(&self, from: Self::Plain, finer: bool) -> Self::Plain {
T::from_index(self.inner.next_step(T::to_index(from) as i32) as usize) T::from_index(self.inner.next_step(T::to_index(from) as i32, finer) as usize)
} }
fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String { fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String {
@ -232,12 +232,12 @@ impl Param for EnumParamInner {
Some(self.len() - 1) Some(self.len() - 1)
} }
fn previous_step(&self, from: Self::Plain) -> Self::Plain { fn previous_step(&self, from: Self::Plain, finer: bool) -> Self::Plain {
self.inner.previous_step(from) self.inner.previous_step(from, finer)
} }
fn next_step(&self, from: Self::Plain) -> Self::Plain { fn next_step(&self, from: Self::Plain, finer: bool) -> Self::Plain {
self.inner.next_step(from) self.inner.next_step(from, finer)
} }
fn normalized_value_to_string(&self, normalized: f32, _include_unit: bool) -> String { fn normalized_value_to_string(&self, normalized: f32, _include_unit: bool) -> String {

View file

@ -130,12 +130,12 @@ impl Param for FloatParam {
None None
} }
fn previous_step(&self, from: Self::Plain) -> Self::Plain { fn previous_step(&self, from: Self::Plain, finer: bool) -> Self::Plain {
self.range.previous_step(from, self.step_size) self.range.previous_step(from, self.step_size, finer)
} }
fn next_step(&self, from: Self::Plain) -> Self::Plain { fn next_step(&self, from: Self::Plain, finer: bool) -> Self::Plain {
self.range.next_step(from, self.step_size) self.range.next_step(from, self.step_size, finer)
} }
fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String { fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String {

View file

@ -122,11 +122,11 @@ impl Param for IntParam {
Some(self.range.step_count()) Some(self.range.step_count())
} }
fn previous_step(&self, from: Self::Plain) -> Self::Plain { fn previous_step(&self, from: Self::Plain, _finer: bool) -> Self::Plain {
self.range.previous_step(from) self.range.previous_step(from)
} }
fn next_step(&self, from: Self::Plain) -> Self::Plain { fn next_step(&self, from: Self::Plain, _finer: bool) -> Self::Plain {
self.range.next_step(from) self.range.next_step(from)
} }

View file

@ -68,8 +68,8 @@ impl ParamPtr {
param_ptr_forward!(pub unsafe fn unmodulated_normalized_value(&self) -> f32); param_ptr_forward!(pub unsafe fn unmodulated_normalized_value(&self) -> f32);
param_ptr_forward!(pub unsafe fn default_normalized_value(&self) -> f32); param_ptr_forward!(pub unsafe fn default_normalized_value(&self) -> f32);
param_ptr_forward!(pub unsafe fn step_count(&self) -> Option<usize>); param_ptr_forward!(pub unsafe fn step_count(&self) -> Option<usize>);
param_ptr_forward!(pub unsafe fn previous_normalized_step(&self, from: f32) -> f32); param_ptr_forward!(pub unsafe fn previous_normalized_step(&self, from: f32, finer: bool) -> f32);
param_ptr_forward!(pub unsafe fn next_normalized_step(&self, from: f32) -> f32); param_ptr_forward!(pub unsafe fn next_normalized_step(&self, from: f32, finer: bool) -> f32);
param_ptr_forward!(pub unsafe fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String); param_ptr_forward!(pub unsafe fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String);
param_ptr_forward!(pub unsafe fn string_to_normalized_value(&self, string: &str) -> Option<f32>); param_ptr_forward!(pub unsafe fn string_to_normalized_value(&self, string: &str) -> Option<f32>);
param_ptr_forward!(pub unsafe fn flags(&self) -> ParamFlags); param_ptr_forward!(pub unsafe fn flags(&self) -> ParamFlags);

View file

@ -130,17 +130,20 @@ impl FloatRange {
} }
} }
/// The range's previous discrete step from a certain value with a certain step size. If the step /// The range's previous discrete step from a certain value with a certain step size. If the
/// size is not set, then the normalized range is split into 100 segments instead. /// step size is not set, then the normalized range is split into 50 segments instead. If
pub fn previous_step(&self, from: f32, step_size: Option<f32>) -> f32 { /// `finer` is true, then this is upped to 200 segments.
pub fn previous_step(&self, from: f32, step_size: Option<f32>, finer: bool) -> f32 {
// This one's slightly more involved than the integer version. We'll split the normalized // This one's slightly more involved than the integer version. We'll split the normalized
// range up into 100 segments, but if `self.step_size` would cause the range to be devided // range up into 50 segments, but if `self.step_size` would cause the range to be devided
// into less than 100 segments then we'll use that. // into less than 50 segments then we'll use that.
match self { match self {
FloatRange::Linear { min, max } FloatRange::Linear { min, max }
| FloatRange::Skewed { min, max, .. } | FloatRange::Skewed { min, max, .. }
| FloatRange::SymmetricalSkewed { min, max, .. } => { | FloatRange::SymmetricalSkewed { min, max, .. } => {
let naive_step = self.unnormalize(self.normalize(from) - 0.01); let normalized_naive_step_size = if finer { 0.005 } else { 0.02 };
let naive_step =
self.unnormalize(self.normalize(from) - normalized_naive_step_size);
match step_size { match step_size {
// Use the naive step size if it is larger than the configured step size // Use the naive step size if it is larger than the configured step size
@ -152,19 +155,21 @@ impl FloatRange {
} }
.clamp(*min, *max) .clamp(*min, *max)
} }
FloatRange::Reversed(range) => range.next_step(from, step_size), FloatRange::Reversed(range) => range.next_step(from, step_size, finer),
} }
} }
/// The range's next discrete step from a certain value with a certain step size. If the step /// The range's next discrete step from a certain value with a certain step size. If the step
/// size is not set, then the normalized range is split into 100 segments instead. /// size is not set, then the normalized range is split into 100 segments instead.
pub fn next_step(&self, from: f32, step_size: Option<f32>) -> f32 { pub fn next_step(&self, from: f32, step_size: Option<f32>, finer: bool) -> f32 {
// See above // See above
match self { match self {
FloatRange::Linear { min, max } FloatRange::Linear { min, max }
| FloatRange::Skewed { min, max, .. } | FloatRange::Skewed { min, max, .. }
| FloatRange::SymmetricalSkewed { min, max, .. } => { | FloatRange::SymmetricalSkewed { min, max, .. } => {
let naive_step = self.unnormalize(self.normalize(from) + 0.01); let normalized_naive_step_size = if finer { 0.005 } else { 0.02 };
let naive_step =
self.unnormalize(self.normalize(from) + normalized_naive_step_size);
match step_size { match step_size {
Some(step_size) if (naive_step - from).abs() > step_size => { Some(step_size) if (naive_step - from).abs() > step_size => {
@ -175,7 +180,7 @@ impl FloatRange {
} }
.clamp(*min, *max) .clamp(*min, *max)
} }
FloatRange::Reversed(range) => range.previous_step(from, step_size), FloatRange::Reversed(range) => range.previous_step(from, step_size, finer),
} }
} }