Flattened PointerAction::Pressed
into Press
and Release
. (#17424)
Fixes #17397. Also renamed all variants into present-tense. ## Migration Guide - `PointerAction::Pressed` has been seperated into two variants, `PointerAction::Press` and `PointerAction::Release`. - `PointerAction::Moved` has been renamed to `PointerAction::Move`. - `PointerAction::Canceled` has been renamed to `PointerAction::Cancel`.
This commit is contained in:
parent
e66aef2d7a
commit
5d0e9cfb36
@ -50,9 +50,7 @@ use tracing::debug;
|
|||||||
use crate::{
|
use crate::{
|
||||||
backend::{prelude::PointerLocation, HitData},
|
backend::{prelude::PointerLocation, HitData},
|
||||||
hover::{HoverMap, PreviousHoverMap},
|
hover::{HoverMap, PreviousHoverMap},
|
||||||
pointer::{
|
pointer::{Location, PointerAction, PointerButton, PointerId, PointerInput, PointerMap},
|
||||||
Location, PointerAction, PointerButton, PointerId, PointerInput, PointerMap, PressDirection,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Stores the common data needed for all pointer events.
|
/// Stores the common data needed for all pointer events.
|
||||||
@ -538,128 +536,123 @@ pub fn pointer_events(
|
|||||||
} in input_events.read().cloned()
|
} in input_events.read().cloned()
|
||||||
{
|
{
|
||||||
match action {
|
match action {
|
||||||
// Pressed Button
|
PointerAction::Press(button) => {
|
||||||
PointerAction::Pressed { direction, button } => {
|
|
||||||
let state = pointer_state.get_mut(pointer_id, button);
|
let state = pointer_state.get_mut(pointer_id, button);
|
||||||
|
|
||||||
// The sequence of events emitted depends on if this is a press or a release
|
// If it's a press, emit a Pressed event and mark the hovered entities as pressed
|
||||||
match direction {
|
for (hovered_entity, hit) in hover_map
|
||||||
PressDirection::Pressed => {
|
.get(&pointer_id)
|
||||||
// If it's a press, emit a Pressed event and mark the hovered entities as pressed
|
.iter()
|
||||||
for (hovered_entity, hit) in hover_map
|
.flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.clone())))
|
||||||
.get(&pointer_id)
|
{
|
||||||
.iter()
|
let pressed_event = Pointer::new(
|
||||||
.flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.clone())))
|
pointer_id,
|
||||||
{
|
location.clone(),
|
||||||
let pressed_event = Pointer::new(
|
hovered_entity,
|
||||||
pointer_id,
|
Pressed {
|
||||||
location.clone(),
|
button,
|
||||||
hovered_entity,
|
hit: hit.clone(),
|
||||||
Pressed {
|
},
|
||||||
button,
|
);
|
||||||
hit: hit.clone(),
|
commands.trigger_targets(pressed_event.clone(), hovered_entity);
|
||||||
},
|
event_writers.pressed_events.send(pressed_event);
|
||||||
);
|
// Also insert the press into the state
|
||||||
commands.trigger_targets(pressed_event.clone(), hovered_entity);
|
state
|
||||||
event_writers.pressed_events.send(pressed_event);
|
.pressing
|
||||||
// Also insert the press into the state
|
.insert(hovered_entity, (location.clone(), now, hit));
|
||||||
state
|
|
||||||
.pressing
|
|
||||||
.insert(hovered_entity, (location.clone(), now, hit));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PressDirection::Released => {
|
|
||||||
// Emit Click and Up events on all the previously hovered entities.
|
|
||||||
for (hovered_entity, hit) in previous_hover_map
|
|
||||||
.get(&pointer_id)
|
|
||||||
.iter()
|
|
||||||
.flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.clone())))
|
|
||||||
{
|
|
||||||
// If this pointer previously pressed the hovered entity, emit a Click event
|
|
||||||
if let Some((_, press_instant, _)) = state.pressing.get(&hovered_entity)
|
|
||||||
{
|
|
||||||
let click_event = Pointer::new(
|
|
||||||
pointer_id,
|
|
||||||
location.clone(),
|
|
||||||
hovered_entity,
|
|
||||||
Click {
|
|
||||||
button,
|
|
||||||
hit: hit.clone(),
|
|
||||||
duration: now - *press_instant,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
commands.trigger_targets(click_event.clone(), hovered_entity);
|
|
||||||
event_writers.click_events.send(click_event);
|
|
||||||
}
|
|
||||||
// Always send the Released event
|
|
||||||
let released_event = Pointer::new(
|
|
||||||
pointer_id,
|
|
||||||
location.clone(),
|
|
||||||
hovered_entity,
|
|
||||||
Released {
|
|
||||||
button,
|
|
||||||
hit: hit.clone(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
commands.trigger_targets(released_event.clone(), hovered_entity);
|
|
||||||
event_writers.released_events.send(released_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then emit the drop events.
|
|
||||||
for (drag_target, drag) in state.dragging.drain() {
|
|
||||||
// Emit DragDrop
|
|
||||||
for (dragged_over, hit) in state.dragging_over.iter() {
|
|
||||||
let drag_drop_event = Pointer::new(
|
|
||||||
pointer_id,
|
|
||||||
location.clone(),
|
|
||||||
*dragged_over,
|
|
||||||
DragDrop {
|
|
||||||
button,
|
|
||||||
dropped: drag_target,
|
|
||||||
hit: hit.clone(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
commands.trigger_targets(drag_drop_event.clone(), *dragged_over);
|
|
||||||
event_writers.drag_drop_events.send(drag_drop_event);
|
|
||||||
}
|
|
||||||
// Emit DragEnd
|
|
||||||
let drag_end_event = Pointer::new(
|
|
||||||
pointer_id,
|
|
||||||
location.clone(),
|
|
||||||
drag_target,
|
|
||||||
DragEnd {
|
|
||||||
button,
|
|
||||||
distance: drag.latest_pos - drag.start_pos,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
commands.trigger_targets(drag_end_event.clone(), drag_target);
|
|
||||||
event_writers.drag_end_events.send(drag_end_event);
|
|
||||||
// Emit DragLeave
|
|
||||||
for (dragged_over, hit) in state.dragging_over.iter() {
|
|
||||||
let drag_leave_event = Pointer::new(
|
|
||||||
pointer_id,
|
|
||||||
location.clone(),
|
|
||||||
*dragged_over,
|
|
||||||
DragLeave {
|
|
||||||
button,
|
|
||||||
dragged: drag_target,
|
|
||||||
hit: hit.clone(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
commands.trigger_targets(drag_leave_event.clone(), *dragged_over);
|
|
||||||
event_writers.drag_leave_events.send(drag_leave_event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, we can clear the state of everything relating to presses or drags.
|
|
||||||
state.pressing.clear();
|
|
||||||
state.dragging.clear();
|
|
||||||
state.dragging_over.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PointerAction::Release(button) => {
|
||||||
|
let state = pointer_state.get_mut(pointer_id, button);
|
||||||
|
|
||||||
|
// Emit Click and Up events on all the previously hovered entities.
|
||||||
|
for (hovered_entity, hit) in previous_hover_map
|
||||||
|
.get(&pointer_id)
|
||||||
|
.iter()
|
||||||
|
.flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.clone())))
|
||||||
|
{
|
||||||
|
// If this pointer previously pressed the hovered entity, emit a Click event
|
||||||
|
if let Some((_, press_instant, _)) = state.pressing.get(&hovered_entity) {
|
||||||
|
let click_event = Pointer::new(
|
||||||
|
pointer_id,
|
||||||
|
location.clone(),
|
||||||
|
hovered_entity,
|
||||||
|
Click {
|
||||||
|
button,
|
||||||
|
hit: hit.clone(),
|
||||||
|
duration: now - *press_instant,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
commands.trigger_targets(click_event.clone(), hovered_entity);
|
||||||
|
event_writers.click_events.send(click_event);
|
||||||
|
}
|
||||||
|
// Always send the Released event
|
||||||
|
let released_event = Pointer::new(
|
||||||
|
pointer_id,
|
||||||
|
location.clone(),
|
||||||
|
hovered_entity,
|
||||||
|
Released {
|
||||||
|
button,
|
||||||
|
hit: hit.clone(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
commands.trigger_targets(released_event.clone(), hovered_entity);
|
||||||
|
event_writers.released_events.send(released_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then emit the drop events.
|
||||||
|
for (drag_target, drag) in state.dragging.drain() {
|
||||||
|
// Emit DragDrop
|
||||||
|
for (dragged_over, hit) in state.dragging_over.iter() {
|
||||||
|
let drag_drop_event = Pointer::new(
|
||||||
|
pointer_id,
|
||||||
|
location.clone(),
|
||||||
|
*dragged_over,
|
||||||
|
DragDrop {
|
||||||
|
button,
|
||||||
|
dropped: drag_target,
|
||||||
|
hit: hit.clone(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
commands.trigger_targets(drag_drop_event.clone(), *dragged_over);
|
||||||
|
event_writers.drag_drop_events.send(drag_drop_event);
|
||||||
|
}
|
||||||
|
// Emit DragEnd
|
||||||
|
let drag_end_event = Pointer::new(
|
||||||
|
pointer_id,
|
||||||
|
location.clone(),
|
||||||
|
drag_target,
|
||||||
|
DragEnd {
|
||||||
|
button,
|
||||||
|
distance: drag.latest_pos - drag.start_pos,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
commands.trigger_targets(drag_end_event.clone(), drag_target);
|
||||||
|
event_writers.drag_end_events.send(drag_end_event);
|
||||||
|
// Emit DragLeave
|
||||||
|
for (dragged_over, hit) in state.dragging_over.iter() {
|
||||||
|
let drag_leave_event = Pointer::new(
|
||||||
|
pointer_id,
|
||||||
|
location.clone(),
|
||||||
|
*dragged_over,
|
||||||
|
DragLeave {
|
||||||
|
button,
|
||||||
|
dragged: drag_target,
|
||||||
|
hit: hit.clone(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
commands.trigger_targets(drag_leave_event.clone(), *dragged_over);
|
||||||
|
event_writers.drag_leave_events.send(drag_leave_event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, we can clear the state of everything relating to presses or drags.
|
||||||
|
state.pressing.clear();
|
||||||
|
state.dragging.clear();
|
||||||
|
state.dragging_over.clear();
|
||||||
|
}
|
||||||
// Moved
|
// Moved
|
||||||
PointerAction::Moved { delta } => {
|
PointerAction::Move { delta } => {
|
||||||
if delta == Vec2::ZERO {
|
if delta == Vec2::ZERO {
|
||||||
continue; // If delta is zero, the following events will not be triggered.
|
continue; // If delta is zero, the following events will not be triggered.
|
||||||
}
|
}
|
||||||
@ -757,7 +750,7 @@ pub fn pointer_events(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Canceled
|
// Canceled
|
||||||
PointerAction::Canceled => {
|
PointerAction::Cancel => {
|
||||||
// Emit a Cancel to the hovered entity.
|
// Emit a Cancel to the hovered entity.
|
||||||
for (hovered_entity, hit) in hover_map
|
for (hovered_entity, hit) in hover_map
|
||||||
.get(&pointer_id)
|
.get(&pointer_id)
|
||||||
|
@ -118,7 +118,7 @@ fn build_over_map(
|
|||||||
let cancelled_pointers: HashSet<PointerId> = pointer_input
|
let cancelled_pointers: HashSet<PointerId> = pointer_input
|
||||||
.read()
|
.read()
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
if let PointerAction::Canceled = p.action {
|
if let PointerAction::Cancel = p.action {
|
||||||
Some(p.pointer_id)
|
Some(p.pointer_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -27,7 +27,6 @@ use tracing::debug;
|
|||||||
|
|
||||||
use crate::pointer::{
|
use crate::pointer::{
|
||||||
Location, PointerAction, PointerButton, PointerId, PointerInput, PointerLocation,
|
Location, PointerAction, PointerButton, PointerId, PointerInput, PointerLocation,
|
||||||
PressDirection,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::PickSet;
|
use crate::PickSet;
|
||||||
@ -128,7 +127,7 @@ pub fn mouse_pick_events(
|
|||||||
pointer_events.send(PointerInput::new(
|
pointer_events.send(PointerInput::new(
|
||||||
PointerId::Mouse,
|
PointerId::Mouse,
|
||||||
location,
|
location,
|
||||||
PointerAction::Moved {
|
PointerAction::Move {
|
||||||
delta: event.position - *cursor_last,
|
delta: event.position - *cursor_last,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
@ -151,15 +150,11 @@ pub fn mouse_pick_events(
|
|||||||
MouseButton::Middle => PointerButton::Middle,
|
MouseButton::Middle => PointerButton::Middle,
|
||||||
MouseButton::Other(_) | MouseButton::Back | MouseButton::Forward => continue,
|
MouseButton::Other(_) | MouseButton::Back | MouseButton::Forward => continue,
|
||||||
};
|
};
|
||||||
let direction = match input.state {
|
let action = match input.state {
|
||||||
ButtonState::Pressed => PressDirection::Pressed,
|
ButtonState::Pressed => PointerAction::Press(button),
|
||||||
ButtonState::Released => PressDirection::Released,
|
ButtonState::Released => PointerAction::Release(button),
|
||||||
};
|
};
|
||||||
pointer_events.send(PointerInput::new(
|
pointer_events.send(PointerInput::new(PointerId::Mouse, location, action));
|
||||||
PointerId::Mouse,
|
|
||||||
location,
|
|
||||||
PointerAction::Pressed { direction, button },
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -197,10 +192,7 @@ pub fn touch_pick_events(
|
|||||||
pointer_events.send(PointerInput::new(
|
pointer_events.send(PointerInput::new(
|
||||||
pointer,
|
pointer,
|
||||||
location,
|
location,
|
||||||
PointerAction::Pressed {
|
PointerAction::Press(PointerButton::Primary),
|
||||||
direction: PressDirection::Pressed,
|
|
||||||
button: PointerButton::Primary,
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
|
|
||||||
touch_cache.insert(touch.id, *touch);
|
touch_cache.insert(touch.id, *touch);
|
||||||
@ -214,7 +206,7 @@ pub fn touch_pick_events(
|
|||||||
pointer_events.send(PointerInput::new(
|
pointer_events.send(PointerInput::new(
|
||||||
pointer,
|
pointer,
|
||||||
location,
|
location,
|
||||||
PointerAction::Moved {
|
PointerAction::Move {
|
||||||
delta: touch.position - last_touch.position,
|
delta: touch.position - last_touch.position,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
@ -225,10 +217,7 @@ pub fn touch_pick_events(
|
|||||||
pointer_events.send(PointerInput::new(
|
pointer_events.send(PointerInput::new(
|
||||||
pointer,
|
pointer,
|
||||||
location,
|
location,
|
||||||
PointerAction::Pressed {
|
PointerAction::Release(PointerButton::Primary),
|
||||||
direction: PressDirection::Released,
|
|
||||||
button: PointerButton::Primary,
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
touch_cache.remove(&touch.id);
|
touch_cache.remove(&touch.id);
|
||||||
}
|
}
|
||||||
@ -236,7 +225,7 @@ pub fn touch_pick_events(
|
|||||||
pointer_events.send(PointerInput::new(
|
pointer_events.send(PointerInput::new(
|
||||||
pointer,
|
pointer,
|
||||||
location,
|
location,
|
||||||
PointerAction::Canceled,
|
PointerAction::Cancel,
|
||||||
));
|
));
|
||||||
touch_cache.remove(&touch.id);
|
touch_cache.remove(&touch.id);
|
||||||
}
|
}
|
||||||
|
@ -239,23 +239,20 @@ impl Location {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Types of actions that can be taken by pointers.
|
/// Event sent to drive a pointer.
|
||||||
#[derive(Debug, Clone, Copy, Reflect)]
|
#[derive(Debug, Clone, Copy, Reflect)]
|
||||||
pub enum PointerAction {
|
pub enum PointerAction {
|
||||||
/// A button has been pressed on the pointer.
|
/// Causes the pointer to press a button.
|
||||||
Pressed {
|
Press(PointerButton),
|
||||||
/// The press state, either pressed or released.
|
/// Causes the pointer to release a button.
|
||||||
direction: PressDirection,
|
Release(PointerButton),
|
||||||
/// The button that was pressed.
|
/// Move the pointer.
|
||||||
button: PointerButton,
|
Move {
|
||||||
},
|
|
||||||
/// The pointer has moved.
|
|
||||||
Moved {
|
|
||||||
/// How much the pointer moved from the previous position.
|
/// How much the pointer moved from the previous position.
|
||||||
delta: Vec2,
|
delta: Vec2,
|
||||||
},
|
},
|
||||||
/// The pointer has been canceled. The OS can cause this to happen to touch events.
|
/// Cancel the pointer. Often used for touch events.
|
||||||
Canceled,
|
Cancel,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An input event effecting a pointer.
|
/// An input event effecting a pointer.
|
||||||
@ -263,7 +260,7 @@ pub enum PointerAction {
|
|||||||
pub struct PointerInput {
|
pub struct PointerInput {
|
||||||
/// The id of the pointer.
|
/// The id of the pointer.
|
||||||
pub pointer_id: PointerId,
|
pub pointer_id: PointerId,
|
||||||
/// The location of the pointer. For [[`PointerAction::Moved`]], this is the location after the movement.
|
/// The location of the pointer. For [`PointerAction::Move`], this is the location after the movement.
|
||||||
pub location: Location,
|
pub location: Location,
|
||||||
/// The action that the event describes.
|
/// The action that the event describes.
|
||||||
pub action: PointerAction,
|
pub action: PointerAction,
|
||||||
@ -284,8 +281,8 @@ impl PointerInput {
|
|||||||
/// Returns true if the `target_button` of this pointer was just pressed.
|
/// Returns true if the `target_button` of this pointer was just pressed.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn button_just_pressed(&self, target_button: PointerButton) -> bool {
|
pub fn button_just_pressed(&self, target_button: PointerButton) -> bool {
|
||||||
if let PointerAction::Pressed { direction, button } = self.action {
|
if let PointerAction::Press(button) = self.action {
|
||||||
direction == PressDirection::Pressed && button == target_button
|
button == target_button
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -294,8 +291,8 @@ impl PointerInput {
|
|||||||
/// Returns true if the `target_button` of this pointer was just released.
|
/// Returns true if the `target_button` of this pointer was just released.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn button_just_released(&self, target_button: PointerButton) -> bool {
|
pub fn button_just_released(&self, target_button: PointerButton) -> bool {
|
||||||
if let PointerAction::Pressed { direction, button } = self.action {
|
if let PointerAction::Release(button) = self.action {
|
||||||
direction == PressDirection::Released && button == target_button
|
button == target_button
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -308,21 +305,33 @@ impl PointerInput {
|
|||||||
) {
|
) {
|
||||||
for event in events.read() {
|
for event in events.read() {
|
||||||
match event.action {
|
match event.action {
|
||||||
PointerAction::Pressed { direction, button } => {
|
PointerAction::Press(button) => {
|
||||||
pointers
|
pointers
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.for_each(|(pointer_id, _, mut pointer)| {
|
.for_each(|(pointer_id, _, mut pointer)| {
|
||||||
if *pointer_id == event.pointer_id {
|
if *pointer_id == event.pointer_id {
|
||||||
let is_pressed = direction == PressDirection::Pressed;
|
|
||||||
match button {
|
match button {
|
||||||
PointerButton::Primary => pointer.primary = is_pressed,
|
PointerButton::Primary => pointer.primary = true,
|
||||||
PointerButton::Secondary => pointer.secondary = is_pressed,
|
PointerButton::Secondary => pointer.secondary = true,
|
||||||
PointerButton::Middle => pointer.middle = is_pressed,
|
PointerButton::Middle => pointer.middle = true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
PointerAction::Moved { .. } => {
|
PointerAction::Release(button) => {
|
||||||
|
pointers
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|(pointer_id, _, mut pointer)| {
|
||||||
|
if *pointer_id == event.pointer_id {
|
||||||
|
match button {
|
||||||
|
PointerButton::Primary => pointer.primary = false,
|
||||||
|
PointerButton::Secondary => pointer.secondary = false,
|
||||||
|
PointerButton::Middle => pointer.middle = false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
PointerAction::Move { .. } => {
|
||||||
pointers.iter_mut().for_each(|(id, mut pointer, _)| {
|
pointers.iter_mut().for_each(|(id, mut pointer, _)| {
|
||||||
if *id == event.pointer_id {
|
if *id == event.pointer_id {
|
||||||
pointer.location = Some(event.location.to_owned());
|
pointer.location = Some(event.location.to_owned());
|
||||||
|
Loading…
Reference in New Issue
Block a user