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::{
|
||||
backend::{prelude::PointerLocation, HitData},
|
||||
hover::{HoverMap, PreviousHoverMap},
|
||||
pointer::{
|
||||
Location, PointerAction, PointerButton, PointerId, PointerInput, PointerMap, PressDirection,
|
||||
},
|
||||
pointer::{Location, PointerAction, PointerButton, PointerId, PointerInput, PointerMap},
|
||||
};
|
||||
|
||||
/// Stores the common data needed for all pointer events.
|
||||
@ -538,128 +536,123 @@ pub fn pointer_events(
|
||||
} in input_events.read().cloned()
|
||||
{
|
||||
match action {
|
||||
// Pressed Button
|
||||
PointerAction::Pressed { direction, button } => {
|
||||
PointerAction::Press(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
|
||||
match direction {
|
||||
PressDirection::Pressed => {
|
||||
// If it's a press, emit a Pressed event and mark the hovered entities as pressed
|
||||
for (hovered_entity, hit) in hover_map
|
||||
.get(&pointer_id)
|
||||
.iter()
|
||||
.flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.clone())))
|
||||
{
|
||||
let pressed_event = Pointer::new(
|
||||
pointer_id,
|
||||
location.clone(),
|
||||
hovered_entity,
|
||||
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
|
||||
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();
|
||||
}
|
||||
// If it's a press, emit a Pressed event and mark the hovered entities as pressed
|
||||
for (hovered_entity, hit) in hover_map
|
||||
.get(&pointer_id)
|
||||
.iter()
|
||||
.flat_map(|h| h.iter().map(|(entity, data)| (*entity, data.clone())))
|
||||
{
|
||||
let pressed_event = Pointer::new(
|
||||
pointer_id,
|
||||
location.clone(),
|
||||
hovered_entity,
|
||||
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
|
||||
state
|
||||
.pressing
|
||||
.insert(hovered_entity, (location.clone(), now, hit));
|
||||
}
|
||||
}
|
||||
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
|
||||
PointerAction::Moved { delta } => {
|
||||
PointerAction::Move { delta } => {
|
||||
if delta == Vec2::ZERO {
|
||||
continue; // If delta is zero, the following events will not be triggered.
|
||||
}
|
||||
@ -757,7 +750,7 @@ pub fn pointer_events(
|
||||
}
|
||||
}
|
||||
// Canceled
|
||||
PointerAction::Canceled => {
|
||||
PointerAction::Cancel => {
|
||||
// Emit a Cancel to the hovered entity.
|
||||
for (hovered_entity, hit) in hover_map
|
||||
.get(&pointer_id)
|
||||
|
@ -118,7 +118,7 @@ fn build_over_map(
|
||||
let cancelled_pointers: HashSet<PointerId> = pointer_input
|
||||
.read()
|
||||
.filter_map(|p| {
|
||||
if let PointerAction::Canceled = p.action {
|
||||
if let PointerAction::Cancel = p.action {
|
||||
Some(p.pointer_id)
|
||||
} else {
|
||||
None
|
||||
|
@ -27,7 +27,6 @@ use tracing::debug;
|
||||
|
||||
use crate::pointer::{
|
||||
Location, PointerAction, PointerButton, PointerId, PointerInput, PointerLocation,
|
||||
PressDirection,
|
||||
};
|
||||
|
||||
use crate::PickSet;
|
||||
@ -128,7 +127,7 @@ pub fn mouse_pick_events(
|
||||
pointer_events.send(PointerInput::new(
|
||||
PointerId::Mouse,
|
||||
location,
|
||||
PointerAction::Moved {
|
||||
PointerAction::Move {
|
||||
delta: event.position - *cursor_last,
|
||||
},
|
||||
));
|
||||
@ -151,15 +150,11 @@ pub fn mouse_pick_events(
|
||||
MouseButton::Middle => PointerButton::Middle,
|
||||
MouseButton::Other(_) | MouseButton::Back | MouseButton::Forward => continue,
|
||||
};
|
||||
let direction = match input.state {
|
||||
ButtonState::Pressed => PressDirection::Pressed,
|
||||
ButtonState::Released => PressDirection::Released,
|
||||
let action = match input.state {
|
||||
ButtonState::Pressed => PointerAction::Press(button),
|
||||
ButtonState::Released => PointerAction::Release(button),
|
||||
};
|
||||
pointer_events.send(PointerInput::new(
|
||||
PointerId::Mouse,
|
||||
location,
|
||||
PointerAction::Pressed { direction, button },
|
||||
));
|
||||
pointer_events.send(PointerInput::new(PointerId::Mouse, location, action));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -197,10 +192,7 @@ pub fn touch_pick_events(
|
||||
pointer_events.send(PointerInput::new(
|
||||
pointer,
|
||||
location,
|
||||
PointerAction::Pressed {
|
||||
direction: PressDirection::Pressed,
|
||||
button: PointerButton::Primary,
|
||||
},
|
||||
PointerAction::Press(PointerButton::Primary),
|
||||
));
|
||||
|
||||
touch_cache.insert(touch.id, *touch);
|
||||
@ -214,7 +206,7 @@ pub fn touch_pick_events(
|
||||
pointer_events.send(PointerInput::new(
|
||||
pointer,
|
||||
location,
|
||||
PointerAction::Moved {
|
||||
PointerAction::Move {
|
||||
delta: touch.position - last_touch.position,
|
||||
},
|
||||
));
|
||||
@ -225,10 +217,7 @@ pub fn touch_pick_events(
|
||||
pointer_events.send(PointerInput::new(
|
||||
pointer,
|
||||
location,
|
||||
PointerAction::Pressed {
|
||||
direction: PressDirection::Released,
|
||||
button: PointerButton::Primary,
|
||||
},
|
||||
PointerAction::Release(PointerButton::Primary),
|
||||
));
|
||||
touch_cache.remove(&touch.id);
|
||||
}
|
||||
@ -236,7 +225,7 @@ pub fn touch_pick_events(
|
||||
pointer_events.send(PointerInput::new(
|
||||
pointer,
|
||||
location,
|
||||
PointerAction::Canceled,
|
||||
PointerAction::Cancel,
|
||||
));
|
||||
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)]
|
||||
pub enum PointerAction {
|
||||
/// A button has been pressed on the pointer.
|
||||
Pressed {
|
||||
/// The press state, either pressed or released.
|
||||
direction: PressDirection,
|
||||
/// The button that was pressed.
|
||||
button: PointerButton,
|
||||
},
|
||||
/// The pointer has moved.
|
||||
Moved {
|
||||
/// Causes the pointer to press a button.
|
||||
Press(PointerButton),
|
||||
/// Causes the pointer to release a button.
|
||||
Release(PointerButton),
|
||||
/// Move the pointer.
|
||||
Move {
|
||||
/// How much the pointer moved from the previous position.
|
||||
delta: Vec2,
|
||||
},
|
||||
/// The pointer has been canceled. The OS can cause this to happen to touch events.
|
||||
Canceled,
|
||||
/// Cancel the pointer. Often used for touch events.
|
||||
Cancel,
|
||||
}
|
||||
|
||||
/// An input event effecting a pointer.
|
||||
@ -263,7 +260,7 @@ pub enum PointerAction {
|
||||
pub struct PointerInput {
|
||||
/// The id of the pointer.
|
||||
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,
|
||||
/// The action that the event describes.
|
||||
pub action: PointerAction,
|
||||
@ -284,8 +281,8 @@ impl PointerInput {
|
||||
/// Returns true if the `target_button` of this pointer was just pressed.
|
||||
#[inline]
|
||||
pub fn button_just_pressed(&self, target_button: PointerButton) -> bool {
|
||||
if let PointerAction::Pressed { direction, button } = self.action {
|
||||
direction == PressDirection::Pressed && button == target_button
|
||||
if let PointerAction::Press(button) = self.action {
|
||||
button == target_button
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -294,8 +291,8 @@ impl PointerInput {
|
||||
/// Returns true if the `target_button` of this pointer was just released.
|
||||
#[inline]
|
||||
pub fn button_just_released(&self, target_button: PointerButton) -> bool {
|
||||
if let PointerAction::Pressed { direction, button } = self.action {
|
||||
direction == PressDirection::Released && button == target_button
|
||||
if let PointerAction::Release(button) = self.action {
|
||||
button == target_button
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -308,21 +305,33 @@ impl PointerInput {
|
||||
) {
|
||||
for event in events.read() {
|
||||
match event.action {
|
||||
PointerAction::Pressed { direction, button } => {
|
||||
PointerAction::Press(button) => {
|
||||
pointers
|
||||
.iter_mut()
|
||||
.for_each(|(pointer_id, _, mut pointer)| {
|
||||
if *pointer_id == event.pointer_id {
|
||||
let is_pressed = direction == PressDirection::Pressed;
|
||||
match button {
|
||||
PointerButton::Primary => pointer.primary = is_pressed,
|
||||
PointerButton::Secondary => pointer.secondary = is_pressed,
|
||||
PointerButton::Middle => pointer.middle = is_pressed,
|
||||
PointerButton::Primary => pointer.primary = true,
|
||||
PointerButton::Secondary => pointer.secondary = true,
|
||||
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, _)| {
|
||||
if *id == event.pointer_id {
|
||||
pointer.location = Some(event.location.to_owned());
|
||||
|
Loading…
Reference in New Issue
Block a user