Fix granular drag when clicking with shift held
This commit is contained in:
parent
986e93b8d0
commit
304b9bdfeb
|
@ -9,10 +9,13 @@ use nih_plug::prelude::{GuiContext, Param, ParamSetter};
|
||||||
use super::util;
|
use super::util;
|
||||||
use super::ParamMessage;
|
use super::ParamMessage;
|
||||||
|
|
||||||
|
/// When shift+dragging a parameter, one pixel dragged corresponds to this much change in the
|
||||||
|
/// noramlized parameter.
|
||||||
|
const GRANULAR_DRAG_MULTIPLIER: f32 = 0.1;
|
||||||
|
|
||||||
/// A slider that integrates with NIH-plug's [`Param`] types.
|
/// A slider that integrates with NIH-plug's [`Param`] types.
|
||||||
///
|
///
|
||||||
/// TODO: There are currently no styling options at all
|
/// TODO: There are currently no styling options at all
|
||||||
/// TODO: Handle Shift+drag for granular drag
|
|
||||||
/// TODO: Handle Alt+click for text entry
|
/// TODO: Handle Alt+click for text entry
|
||||||
pub struct ParamSlider<'a, P: Param, Renderer: text::Renderer> {
|
pub struct ParamSlider<'a, P: Param, Renderer: text::Renderer> {
|
||||||
state: &'a mut State,
|
state: &'a mut State,
|
||||||
|
@ -31,8 +34,11 @@ pub struct ParamSlider<'a, P: Param, Renderer: text::Renderer> {
|
||||||
/// State for a [`ParamSlider`].
|
/// State for a [`ParamSlider`].
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
drag_active: bool,
|
|
||||||
keyboard_modifiers: keyboard::Modifiers,
|
keyboard_modifiers: keyboard::Modifiers,
|
||||||
|
drag_active: bool,
|
||||||
|
/// We keep track of the start coordinate holding down Shift while dragging for higher precision
|
||||||
|
/// dragging. This is a `None` value when granular dragging is not active.
|
||||||
|
granular_drag_start_x: Option<f32>,
|
||||||
/// Track clicks for double clicks.
|
/// Track clicks for double clicks.
|
||||||
last_click: Option<mouse::Click>,
|
last_click: Option<mouse::Click>,
|
||||||
/// Will be set to `true` if we just reset the parameter since you could otherwise reset the
|
/// Will be set to `true` if we just reset the parameter since you could otherwise reset the
|
||||||
|
@ -117,25 +123,35 @@ impl<'a, P: Param, Renderer: text::Renderer> Widget<ParamMessage, Renderer>
|
||||||
| Event::Touch(touch::Event::FingerPressed { .. }) => {
|
| Event::Touch(touch::Event::FingerPressed { .. }) => {
|
||||||
if bounds.contains(cursor_position) {
|
if bounds.contains(cursor_position) {
|
||||||
shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr()));
|
shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr()));
|
||||||
|
|
||||||
self.state.drag_active = true;
|
self.state.drag_active = true;
|
||||||
|
|
||||||
// Immediately trigger a parameter update if the value would be different, or
|
|
||||||
// reset the parameter if Ctrl is held or the parameter is being double clicked
|
|
||||||
let click = mouse::Click::new(cursor_position, self.state.last_click);
|
let click = mouse::Click::new(cursor_position, self.state.last_click);
|
||||||
self.state.last_click = Some(click);
|
self.state.last_click = Some(click);
|
||||||
if self.state.keyboard_modifiers.control()
|
if self.state.keyboard_modifiers.command()
|
||||||
|| matches!(click.kind(), mouse::click::Kind::Double)
|
|| matches!(click.kind(), mouse::click::Kind::Double)
|
||||||
{
|
{
|
||||||
|
// Immediately trigger a parameter update if the value would be different, or
|
||||||
|
// reset the parameter if Ctrl is held or the parameter is being double clicked
|
||||||
self.set_normalized_value(
|
self.set_normalized_value(
|
||||||
shell,
|
shell,
|
||||||
self.setter.default_normalized_param_value(self.param),
|
self.setter.default_normalized_param_value(self.param),
|
||||||
);
|
);
|
||||||
self.state.ignore_changes = true;
|
self.state.ignore_changes = true;
|
||||||
|
} else if self.state.keyboard_modifiers.shift() {
|
||||||
|
// When holding down shift while clicking on a parameter we want to
|
||||||
|
// granuarly edit the parameter without jumping to a new value
|
||||||
|
self.state.granular_drag_start_x =
|
||||||
|
Some(util::remap_rect_x_t(&bounds, self.param.normalized_value()));
|
||||||
|
|
||||||
|
self.state.ignore_changes = false;
|
||||||
} else {
|
} else {
|
||||||
self.set_normalized_value(
|
self.set_normalized_value(
|
||||||
shell,
|
shell,
|
||||||
util::remap_rect_x_coordinate(&bounds, cursor_position.x),
|
util::remap_rect_x_coordinate(&bounds, cursor_position.x),
|
||||||
);
|
);
|
||||||
|
self.state.granular_drag_start_x = None;
|
||||||
|
|
||||||
self.state.ignore_changes = false;
|
self.state.ignore_changes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +162,7 @@ impl<'a, P: Param, Renderer: text::Renderer> Widget<ParamMessage, Renderer>
|
||||||
| Event::Touch(touch::Event::FingerLifted { .. } | touch::Event::FingerLost { .. }) => {
|
| Event::Touch(touch::Event::FingerLifted { .. } | touch::Event::FingerLost { .. }) => {
|
||||||
if bounds.contains(cursor_position) {
|
if bounds.contains(cursor_position) {
|
||||||
shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr()));
|
shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr()));
|
||||||
|
|
||||||
self.state.drag_active = false;
|
self.state.drag_active = false;
|
||||||
|
|
||||||
return event::Status::Captured;
|
return event::Status::Captured;
|
||||||
|
@ -158,10 +175,30 @@ impl<'a, P: Param, Renderer: text::Renderer> Widget<ParamMessage, Renderer>
|
||||||
&& self.state.drag_active
|
&& self.state.drag_active
|
||||||
&& bounds.contains(cursor_position)
|
&& bounds.contains(cursor_position)
|
||||||
{
|
{
|
||||||
self.set_normalized_value(
|
// If shift is being held then the drag should be more granular instead of
|
||||||
shell,
|
// absolute
|
||||||
util::remap_rect_x_coordinate(&bounds, cursor_position.x),
|
if self.state.keyboard_modifiers.shift() {
|
||||||
);
|
let drag_start_x = *self
|
||||||
|
.state
|
||||||
|
.granular_drag_start_x
|
||||||
|
.get_or_insert(cursor_position.x);
|
||||||
|
|
||||||
|
self.set_normalized_value(
|
||||||
|
shell,
|
||||||
|
util::remap_rect_x_coordinate(
|
||||||
|
&bounds,
|
||||||
|
drag_start_x
|
||||||
|
+ (cursor_position.x - drag_start_x) * GRANULAR_DRAG_MULTIPLIER,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.state.granular_drag_start_x = None;
|
||||||
|
|
||||||
|
self.set_normalized_value(
|
||||||
|
shell,
|
||||||
|
util::remap_rect_x_coordinate(&bounds, cursor_position.x),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return event::Status::Captured;
|
return event::Status::Captured;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue