diff --git a/crates/bevy_picking/src/events.rs b/crates/bevy_picking/src/events.rs index c580c1e59493a..ba1fc18b6c5b3 100644 --- a/crates/bevy_picking/src/events.rs +++ b/crates/bevy_picking/src/events.rs @@ -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); - } + // 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. } @@ -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) diff --git a/crates/bevy_picking/src/hover.rs b/crates/bevy_picking/src/hover.rs index 2b3a68fe8772a..e9545afd3a3e2 100644 --- a/crates/bevy_picking/src/hover.rs +++ b/crates/bevy_picking/src/hover.rs @@ -118,7 +118,7 @@ fn build_over_map( let cancelled_pointers: HashSet = pointer_input .read() .filter_map(|p| { - if let PointerAction::Canceled = p.action { + if let PointerAction::Cancel = p.action { Some(p.pointer_id) } else { None diff --git a/crates/bevy_picking/src/input.rs b/crates/bevy_picking/src/input.rs index 3c03ba11dd525..25fe80da4056e 100644 --- a/crates/bevy_picking/src/input.rs +++ b/crates/bevy_picking/src/input.rs @@ -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); } diff --git a/crates/bevy_picking/src/pointer.rs b/crates/bevy_picking/src/pointer.rs index 42291f7a7daa6..3f82bd1f1a1e0 100644 --- a/crates/bevy_picking/src/pointer.rs +++ b/crates/bevy_picking/src/pointer.rs @@ -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 { + match button { + PointerButton::Primary => pointer.primary = true, + PointerButton::Secondary => pointer.secondary = true, + PointerButton::Middle => pointer.middle = true, + } + } + }); + } + PointerAction::Release(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 = false, + PointerButton::Secondary => pointer.secondary = false, + PointerButton::Middle => pointer.middle = false, } } }); } - PointerAction::Moved { .. } => { + PointerAction::Move { .. } => { pointers.iter_mut().for_each(|(id, mut pointer, _)| { if *id == event.pointer_id { pointer.location = Some(event.location.to_owned());