Fix menus and interactive popups not closing when framerate was low (#4757)
This commit is contained in:
parent
8ef0e85b85
commit
fcb7764e48
|
@ -726,6 +726,9 @@ pub struct PointerState {
|
||||||
/// Current velocity of pointer.
|
/// Current velocity of pointer.
|
||||||
velocity: Vec2,
|
velocity: Vec2,
|
||||||
|
|
||||||
|
/// Current direction of pointer.
|
||||||
|
direction: Vec2,
|
||||||
|
|
||||||
/// Recent movement of the pointer.
|
/// Recent movement of the pointer.
|
||||||
/// Used for calculating velocity of pointer.
|
/// Used for calculating velocity of pointer.
|
||||||
pos_history: History<Pos2>,
|
pos_history: History<Pos2>,
|
||||||
|
@ -774,7 +777,8 @@ impl Default for PointerState {
|
||||||
delta: Vec2::ZERO,
|
delta: Vec2::ZERO,
|
||||||
motion: None,
|
motion: None,
|
||||||
velocity: Vec2::ZERO,
|
velocity: Vec2::ZERO,
|
||||||
pos_history: History::new(0..1000, 0.1),
|
direction: Vec2::ZERO,
|
||||||
|
pos_history: History::new(2..1000, 0.1),
|
||||||
down: Default::default(),
|
down: Default::default(),
|
||||||
press_origin: None,
|
press_origin: None,
|
||||||
press_start_time: None,
|
press_start_time: None,
|
||||||
|
@ -889,6 +893,7 @@ impl PointerState {
|
||||||
// When dragging a slider and the mouse leaves the viewport, we still want the drag to work,
|
// When dragging a slider and the mouse leaves the viewport, we still want the drag to work,
|
||||||
// so we don't treat this as a `PointerEvent::Released`.
|
// so we don't treat this as a `PointerEvent::Released`.
|
||||||
// NOTE: we do NOT clear `self.interact_pos` here. It will be cleared next frame.
|
// NOTE: we do NOT clear `self.interact_pos` here. It will be cleared next frame.
|
||||||
|
self.pos_history.clear();
|
||||||
}
|
}
|
||||||
Event::MouseMoved(delta) => *self.motion.get_or_insert(Vec2::ZERO) += *delta,
|
Event::MouseMoved(delta) => *self.motion.get_or_insert(Vec2::ZERO) += *delta,
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -920,6 +925,8 @@ impl PointerState {
|
||||||
self.last_move_time = time;
|
self.last_move_time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.direction = self.pos_history.velocity().unwrap_or_default().normalized();
|
||||||
|
|
||||||
self.started_decidedly_dragging = self.is_decidedly_dragging() && !was_decidedly_dragging;
|
self.started_decidedly_dragging = self.is_decidedly_dragging() && !was_decidedly_dragging;
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -944,11 +951,22 @@ impl PointerState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Current velocity of pointer.
|
/// Current velocity of pointer.
|
||||||
|
///
|
||||||
|
/// This is smoothed over a few frames,
|
||||||
|
/// but can be ZERO when frame-rate is bad.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn velocity(&self) -> Vec2 {
|
pub fn velocity(&self) -> Vec2 {
|
||||||
self.velocity
|
self.velocity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Current direction of the pointer.
|
||||||
|
///
|
||||||
|
/// This is less sensitive to bad framerate than [`Self::velocity`].
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn direction(&self) -> Vec2 {
|
||||||
|
self.direction
|
||||||
|
}
|
||||||
|
|
||||||
/// Where did the current click/drag originate?
|
/// Where did the current click/drag originate?
|
||||||
/// `None` if no mouse button is down.
|
/// `None` if no mouse button is down.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -1284,6 +1302,7 @@ impl PointerState {
|
||||||
delta,
|
delta,
|
||||||
motion,
|
motion,
|
||||||
velocity,
|
velocity,
|
||||||
|
direction,
|
||||||
pos_history: _,
|
pos_history: _,
|
||||||
down,
|
down,
|
||||||
press_origin,
|
press_origin,
|
||||||
|
@ -1304,6 +1323,7 @@ impl PointerState {
|
||||||
"velocity: [{:3.0} {:3.0}] points/sec",
|
"velocity: [{:3.0} {:3.0}] points/sec",
|
||||||
velocity.x, velocity.y
|
velocity.x, velocity.y
|
||||||
));
|
));
|
||||||
|
ui.label(format!("direction: {direction:?}"));
|
||||||
ui.label(format!("down: {down:#?}"));
|
ui.label(format!("down: {down:#?}"));
|
||||||
ui.label(format!("press_origin: {press_origin:?}"));
|
ui.label(format!("press_origin: {press_origin:?}"));
|
||||||
ui.label(format!("press_start_time: {press_start_time:?} s"));
|
ui.label(format!("press_start_time: {press_start_time:?} s"));
|
||||||
|
|
|
@ -683,7 +683,7 @@ impl MenuState {
|
||||||
if let Some(sub_menu) = self.current_submenu() {
|
if let Some(sub_menu) = self.current_submenu() {
|
||||||
if let Some(pos) = pointer.hover_pos() {
|
if let Some(pos) = pointer.hover_pos() {
|
||||||
let rect = sub_menu.read().rect;
|
let rect = sub_menu.read().rect;
|
||||||
return rect.intersects_ray(pos, pointer.velocity().normalized());
|
return rect.intersects_ray(pos, pointer.direction().normalized());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
|
|
@ -594,9 +594,9 @@ impl Response {
|
||||||
let is_tooltip_open = self.is_tooltip_open();
|
let is_tooltip_open = self.is_tooltip_open();
|
||||||
|
|
||||||
if is_tooltip_open {
|
if is_tooltip_open {
|
||||||
let (pointer_pos, pointer_vel) = self
|
let (pointer_pos, pointer_dir) = self
|
||||||
.ctx
|
.ctx
|
||||||
.input(|i| (i.pointer.hover_pos(), i.pointer.velocity()));
|
.input(|i| (i.pointer.hover_pos(), i.pointer.direction()));
|
||||||
|
|
||||||
if let Some(pointer_pos) = pointer_pos {
|
if let Some(pointer_pos) = pointer_pos {
|
||||||
if self.rect.contains(pointer_pos) {
|
if self.rect.contains(pointer_pos) {
|
||||||
|
@ -624,7 +624,7 @@ impl Response {
|
||||||
|
|
||||||
if let Some(pos) = pointer_pos {
|
if let Some(pos) = pointer_pos {
|
||||||
let pointer_in_area_or_on_the_way_there = rect.contains(pos)
|
let pointer_in_area_or_on_the_way_there = rect.contains(pos)
|
||||||
|| rect.intersects_ray(pos, pointer_vel.normalized());
|
|| rect.intersects_ray(pos, pointer_dir.normalized());
|
||||||
|
|
||||||
if pointer_in_area_or_on_the_way_there {
|
if pointer_in_area_or_on_the_way_there {
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue