Skip to content

Commit

Permalink
Flattened PointerAction::Pressed into Press and Release. (#17424)
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
AlephCubed authored Jan 19, 2025
1 parent e66aef2 commit 5d0e9cf
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 162 deletions.
229 changes: 111 additions & 118 deletions crates/bevy_picking/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
}
// 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);

// 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);
}
}
// 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);
}

// Finally, we can clear the state of everything relating to presses or drags.
state.pressing.clear();
state.dragging.clear();
state.dragging_over.clear();
// 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.
}
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_picking/src/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 9 additions & 20 deletions crates/bevy_picking/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use tracing::debug;

use crate::pointer::{
Location, PointerAction, PointerButton, PointerId, PointerInput, PointerLocation,
PressDirection,
};

use crate::PickSet;
Expand Down Expand Up @@ -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,
},
));
Expand All @@ -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));
}
_ => {}
}
Expand Down Expand Up @@ -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);
Expand All @@ -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,
},
));
Expand All @@ -225,18 +217,15 @@ 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);
}
TouchPhase::Canceled => {
pointer_events.send(PointerInput::new(
pointer,
location,
PointerAction::Canceled,
PointerAction::Cancel,
));
touch_cache.remove(&touch.id);
}
Expand Down
Loading

0 comments on commit 5d0e9cf

Please sign in to comment.