add functions to check which button triggered a drag start & end (#2507)
* add button release events for drags * add utility functions * fix CHANGELOG.md * fix CHANGELOG.md Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
parent
4bd4eca2e4
commit
eee4cf6a82
4 changed files with 61 additions and 29 deletions
|
@ -6,6 +6,8 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
### Added ⭐
|
### Added ⭐
|
||||||
|
* Add `Response::drag_started_by` and `Response::drag_released_by` for convenience, similar to `dragged` and `dragged_by` ([#2507](https://github.com/emilk/egui/pull/2507)).
|
||||||
|
* Add `PointerState::*_pressed` to check if the given button was pressed in this frame ([#2507](https://github.com/emilk/egui/pull/2507)).
|
||||||
* `Event::Key` now has a `repeat` field that is set to `true` if the event was the result of a key-repeat ([#2435](https://github.com/emilk/egui/pull/2435)).
|
* `Event::Key` now has a `repeat` field that is set to `true` if the event was the result of a key-repeat ([#2435](https://github.com/emilk/egui/pull/2435)).
|
||||||
* Add `Slider::drag_value_speed`, which lets you ask for finer precision when dragging the slider value rather than the actual slider.
|
* Add `Slider::drag_value_speed`, which lets you ask for finer precision when dragging the slider value rather than the actual slider.
|
||||||
* Add `Memory::any_popup_open`, which returns true if any popup is currently open ([#2464](https://github.com/emilk/egui/pull/2464)).
|
* Add `Memory::any_popup_open`, which returns true if any popup is currently open ([#2464](https://github.com/emilk/egui/pull/2464)).
|
||||||
|
@ -23,6 +25,7 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG
|
||||||
* Default `ComboBox` is now controlled with `Spacing::combo_width` ([#2621](https://github.com/emilk/egui/pull/2621)).
|
* Default `ComboBox` is now controlled with `Spacing::combo_width` ([#2621](https://github.com/emilk/egui/pull/2621)).
|
||||||
|
|
||||||
### Fixed 🐛
|
### Fixed 🐛
|
||||||
|
* Trigger `PointerEvent::Released` for drags ([#2507](https://github.com/emilk/egui/pull/2507)).
|
||||||
* Expose `TextEdit`'s multiline flag to AccessKit ([#2448](https://github.com/emilk/egui/pull/2448)).
|
* Expose `TextEdit`'s multiline flag to AccessKit ([#2448](https://github.com/emilk/egui/pull/2448)).
|
||||||
* Don't render `\r` (Carriage Return) ([#2452](https://github.com/emilk/egui/pull/2452)).
|
* Don't render `\r` (Carriage Return) ([#2452](https://github.com/emilk/egui/pull/2452)).
|
||||||
* The `button_padding` style option works closer as expected with image+text buttons now ([#2510](https://github.com/emilk/egui/pull/2510)).
|
* The `button_padding` style option works closer as expected with image+text buttons now ([#2510](https://github.com/emilk/egui/pull/2510)).
|
||||||
|
|
|
@ -564,17 +564,17 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PointerEvent::Released(click) => {
|
PointerEvent::Released { click, button } => {
|
||||||
response.drag_released = response.dragged;
|
response.drag_released = response.dragged;
|
||||||
response.dragged = false;
|
response.dragged = false;
|
||||||
|
|
||||||
if hovered && response.is_pointer_button_down_on {
|
if hovered && response.is_pointer_button_down_on {
|
||||||
if let Some(click) = click {
|
if let Some(click) = click {
|
||||||
let clicked = hovered && response.is_pointer_button_down_on;
|
let clicked = hovered && response.is_pointer_button_down_on;
|
||||||
response.clicked[click.button as usize] = clicked;
|
response.clicked[*button as usize] = clicked;
|
||||||
response.double_clicked[click.button as usize] =
|
response.double_clicked[*button as usize] =
|
||||||
clicked && click.is_double();
|
clicked && click.is_double();
|
||||||
response.triple_clicked[click.button as usize] =
|
response.triple_clicked[*button as usize] =
|
||||||
clicked && click.is_triple();
|
clicked && click.is_triple();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,7 +447,6 @@ impl InputState {
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub(crate) struct Click {
|
pub(crate) struct Click {
|
||||||
pub pos: Pos2,
|
pub pos: Pos2,
|
||||||
pub button: PointerButton,
|
|
||||||
/// 1 or 2 (double-click) or 3 (triple-click)
|
/// 1 or 2 (double-click) or 3 (triple-click)
|
||||||
pub count: u32,
|
pub count: u32,
|
||||||
/// Allows you to check for e.g. shift-click
|
/// Allows you to check for e.g. shift-click
|
||||||
|
@ -471,7 +470,10 @@ pub(crate) enum PointerEvent {
|
||||||
position: Pos2,
|
position: Pos2,
|
||||||
button: PointerButton,
|
button: PointerButton,
|
||||||
},
|
},
|
||||||
Released(Option<Click>),
|
Released {
|
||||||
|
click: Option<Click>,
|
||||||
|
button: PointerButton,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PointerEvent {
|
impl PointerEvent {
|
||||||
|
@ -480,11 +482,11 @@ impl PointerEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_release(&self) -> bool {
|
pub fn is_release(&self) -> bool {
|
||||||
matches!(self, PointerEvent::Released(_))
|
matches!(self, PointerEvent::Released { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_click(&self) -> bool {
|
pub fn is_click(&self) -> bool {
|
||||||
matches!(self, PointerEvent::Released(Some(_click)))
|
matches!(self, PointerEvent::Released { click: Some(_), .. })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,7 +641,6 @@ impl PointerState {
|
||||||
|
|
||||||
Some(Click {
|
Some(Click {
|
||||||
pos,
|
pos,
|
||||||
button,
|
|
||||||
count,
|
count,
|
||||||
modifiers,
|
modifiers,
|
||||||
})
|
})
|
||||||
|
@ -647,7 +648,8 @@ impl PointerState {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
self.pointer_events.push(PointerEvent::Released(click));
|
self.pointer_events
|
||||||
|
.push(PointerEvent::Released { click, button });
|
||||||
|
|
||||||
self.press_origin = None;
|
self.press_origin = None;
|
||||||
self.press_start_time = None;
|
self.press_start_time = None;
|
||||||
|
@ -775,11 +777,28 @@ impl PointerState {
|
||||||
self.pointer_events.iter().any(|event| event.is_release())
|
self.pointer_events.iter().any(|event| event.is_release())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Was the button given pressed this frame?
|
||||||
|
pub fn button_pressed(&self, button: PointerButton) -> bool {
|
||||||
|
self.pointer_events
|
||||||
|
.iter()
|
||||||
|
.any(|event| matches!(event, &PointerEvent::Pressed{button: b, ..} if button == b))
|
||||||
|
}
|
||||||
|
|
||||||
/// Was the button given released this frame?
|
/// Was the button given released this frame?
|
||||||
pub fn button_released(&self, button: PointerButton) -> bool {
|
pub fn button_released(&self, button: PointerButton) -> bool {
|
||||||
self.pointer_events
|
self.pointer_events
|
||||||
.iter()
|
.iter()
|
||||||
.any(|event| matches!(event, &PointerEvent::Released(Some(Click{button: b, ..})) if button == b))
|
.any(|event| matches!(event, &PointerEvent::Released{button: b, ..} if button == b))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Was the primary button pressed this frame?
|
||||||
|
pub fn primary_pressed(&self) -> bool {
|
||||||
|
self.button_pressed(PointerButton::Primary)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Was the secondary button pressed this frame?
|
||||||
|
pub fn secondary_pressed(&self) -> bool {
|
||||||
|
self.button_pressed(PointerButton::Secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Was the primary button released this frame?
|
/// Was the primary button released this frame?
|
||||||
|
@ -811,16 +830,28 @@ impl PointerState {
|
||||||
|
|
||||||
/// Was the button given double clicked this frame?
|
/// Was the button given double clicked this frame?
|
||||||
pub fn button_double_clicked(&self, button: PointerButton) -> bool {
|
pub fn button_double_clicked(&self, button: PointerButton) -> bool {
|
||||||
self.pointer_events
|
self.pointer_events.iter().any(|event| {
|
||||||
.iter()
|
matches!(
|
||||||
.any(|event| matches!(&event, PointerEvent::Released(Some(click)) if click.button == button && click.is_double()))
|
&event,
|
||||||
|
PointerEvent::Released {
|
||||||
|
click: Some(click),
|
||||||
|
button: b,
|
||||||
|
} if *b == button && click.is_double()
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Was the button given triple clicked this frame?
|
/// Was the button given triple clicked this frame?
|
||||||
pub fn button_triple_clicked(&self, button: PointerButton) -> bool {
|
pub fn button_triple_clicked(&self, button: PointerButton) -> bool {
|
||||||
self.pointer_events
|
self.pointer_events.iter().any(|event| {
|
||||||
.iter()
|
matches!(
|
||||||
.any(|event| matches!(&event, PointerEvent::Released(Some(click)) if click.button == button && click.is_triple()))
|
&event,
|
||||||
|
PointerEvent::Released {
|
||||||
|
click: Some(click),
|
||||||
|
button: b,
|
||||||
|
} if *b == button && click.is_triple()
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Was the primary button clicked this frame?
|
/// Was the primary button clicked this frame?
|
||||||
|
@ -833,18 +864,6 @@ impl PointerState {
|
||||||
self.button_clicked(PointerButton::Secondary)
|
self.button_clicked(PointerButton::Secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// Was this button pressed (`!down -> down`) this frame?
|
|
||||||
// /// This can sometimes return `true` even if `any_down() == false`
|
|
||||||
// /// because a press can be shorted than one frame.
|
|
||||||
// pub fn button_pressed(&self, button: PointerButton) -> bool {
|
|
||||||
// self.pointer_events.iter().any(|event| event.is_press())
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// Was this button released (`down -> !down`) this frame?
|
|
||||||
// pub fn button_released(&self, button: PointerButton) -> bool {
|
|
||||||
// self.pointer_events.iter().any(|event| event.is_release())
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// Is this button currently down?
|
/// Is this button currently down?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn button_down(&self, button: PointerButton) -> bool {
|
pub fn button_down(&self, button: PointerButton) -> bool {
|
||||||
|
|
|
@ -278,11 +278,21 @@ impl Response {
|
||||||
self.dragged && self.ctx.input().pointer.any_pressed()
|
self.dragged && self.ctx.input().pointer.any_pressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Did a drag on this widgets by the button begin this frame?
|
||||||
|
pub fn drag_started_by(&self, button: PointerButton) -> bool {
|
||||||
|
self.drag_started() && self.ctx.input().pointer.button_pressed(button)
|
||||||
|
}
|
||||||
|
|
||||||
/// The widget was being dragged, but now it has been released.
|
/// The widget was being dragged, but now it has been released.
|
||||||
pub fn drag_released(&self) -> bool {
|
pub fn drag_released(&self) -> bool {
|
||||||
self.drag_released
|
self.drag_released
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The widget was being dragged by the button, but now it has been released.
|
||||||
|
pub fn drag_released_by(&self, button: PointerButton) -> bool {
|
||||||
|
self.drag_released() && self.ctx.input().pointer.button_released(button)
|
||||||
|
}
|
||||||
|
|
||||||
/// If dragged, how many points were we dragged and in what direction?
|
/// If dragged, how many points were we dragged and in what direction?
|
||||||
pub fn drag_delta(&self) -> Vec2 {
|
pub fn drag_delta(&self) -> Vec2 {
|
||||||
if self.dragged() {
|
if self.dragged() {
|
||||||
|
|
Loading…
Reference in a new issue