1
0
Fork 0

Add stepping functions to Param

This can be useful for GUI widgets.
This commit is contained in:
Robbert van der Helm 2022-03-19 16:06:20 +01:00
parent 629619256e
commit d9330628c0
6 changed files with 105 additions and 5 deletions

View file

@ -30,9 +30,22 @@ pub trait Param: Display {
/// Get the unit label for this parameter, if any.
fn unit(&self) -> &'static str;
/// Get the number of steps for this paramter, if it is stepped. Used for the host's generic UI.
/// Get the number of steps for this paramter, if it is discrete. Used for the host's generic
/// UI.
fn step_count(&self) -> Option<usize>;
/// Return the previous step from a specific value for this parameter. This can be the same as
/// `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
/// hundredth of the normalized range instead.
fn previous_step(&self, from: Self::Plain) -> Self::Plain;
/// Return 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
/// interaction in plugin GUIs. When the parameter is not discrete then a step should cover one
/// hundredth of the normalized range instead.
fn next_step(&self, from: Self::Plain) -> Self::Plain;
/// Get the unnormalized value for this parameter.
fn plain_value(&self) -> Self::Plain;

View file

@ -66,6 +66,14 @@ impl Param for BoolParam {
Some(1)
}
fn previous_step(&self, _from: Self::Plain) -> Self::Plain {
false
}
fn next_step(&self, _from: Self::Plain) -> Self::Plain {
true
}
fn plain_value(&self) -> Self::Plain {
self.value
}

View file

@ -113,6 +113,14 @@ impl<T: Enum + PartialEq> Param for EnumParam<T> {
self.inner.step_count()
}
fn previous_step(&self, from: Self::Plain) -> Self::Plain {
T::from_index(self.inner.previous_step(T::to_index(from) as i32) as usize)
}
fn next_step(&self, from: Self::Plain) -> Self::Plain {
T::from_index(self.inner.next_step(T::to_index(from) as i32) as usize)
}
fn plain_value(&self) -> Self::Plain {
T::from_index(self.inner.plain_value() as usize)
}
@ -174,6 +182,14 @@ impl Param for EnumParamInner {
Some(self.len() - 1)
}
fn previous_step(&self, from: Self::Plain) -> Self::Plain {
self.inner.previous_step(from)
}
fn next_step(&self, from: Self::Plain) -> Self::Plain {
self.inner.next_step(from)
}
fn plain_value(&self) -> Self::Plain {
self.inner.plain_value()
}

View file

@ -107,6 +107,29 @@ impl Param for FloatParam {
None
}
fn previous_step(&self, from: Self::Plain) -> Self::Plain {
// This one's slightly more involved. We'll split the normalized range up into 100 segments,
// but if `self.step_size` is set then we'll use that. Ideally we might want to split the
// range up into at most 100 segments, falling back to the step size if the total number of
// steps would be smaller than that, but since ranges can be nonlienar that's a bit
// difficult to pull off.
// TODO: At some point, implement the above mentioned step size quantization
match self.step_size {
Some(step_size) => from - step_size,
None => self.preview_plain(self.preview_normalized(from) - 0.01),
}
.clamp(self.range.min(), self.range.max())
}
fn next_step(&self, from: Self::Plain) -> Self::Plain {
// See above
match self.step_size {
Some(step_size) => from + step_size,
None => self.preview_plain(self.preview_normalized(from) + 0.01),
}
.clamp(self.range.min(), self.range.max())
}
fn plain_value(&self) -> Self::Plain {
self.value
}

View file

@ -95,7 +95,15 @@ impl Param for IntParam {
}
fn step_count(&self) -> Option<usize> {
self.range.step_count()
Some(self.range.step_count())
}
fn previous_step(&self, from: Self::Plain) -> Self::Plain {
(from - 1).clamp(self.range.min(), self.range.max())
}
fn next_step(&self, from: Self::Plain) -> Self::Plain {
(from + 1).clamp(self.range.min(), self.range.max())
}
fn plain_value(&self) -> Self::Plain {

View file

@ -118,6 +118,24 @@ impl FloatRange {
}
}
/// The minimum value in this range.
pub fn min(&self) -> f32 {
match self {
FloatRange::Linear { min, .. }
| FloatRange::Skewed { min, .. }
| FloatRange::SymmetricalSkewed { min, .. } => *min,
}
}
/// The maximum value in this range.
pub fn max(&self) -> f32 {
match self {
FloatRange::Linear { max, .. }
| FloatRange::Skewed { max, .. }
| FloatRange::SymmetricalSkewed { max, .. } => *max,
}
}
/// Snap a vlue to a step size, clamping to the minimum and maximum value of the range.
pub fn snap_to_step(&self, value: f32, step_size: f32) -> f32 {
let (min, max) = match &self {
@ -149,10 +167,24 @@ impl IntRange {
}
}
/// The number of steps in this range, if it is stepped. Used for the host's generic UI.
pub fn step_count(&self) -> Option<usize> {
/// The minimum value in this range.
pub fn min(&self) -> i32 {
match self {
IntRange::Linear { min, max } => Some((max - min) as usize),
IntRange::Linear { min, .. } => *min,
}
}
/// The maximum value in this range.
pub fn max(&self) -> i32 {
match self {
IntRange::Linear { max, .. } => *max,
}
}
/// The number of steps in this range. Used for the host's generic UI.
pub fn step_count(&self) -> usize {
match self {
IntRange::Linear { min, max } => (max - min) as usize,
}
}
}