diff --git a/crates/bevy_picking/Cargo.toml b/crates/bevy_picking/Cargo.toml index 70d470ffc134f..307079147f1d6 100644 --- a/crates/bevy_picking/Cargo.toml +++ b/crates/bevy_picking/Cargo.toml @@ -32,7 +32,6 @@ bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-d # other crossbeam-channel = { version = "0.5", optional = true } -uuid = { version = "1.13.1", features = ["v4"] } tracing = { version = "0.1", default-features = false, features = ["std"] } [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/crates/bevy_picking/src/input.rs b/crates/bevy_picking/src/input.rs index eeb4adac15d3a..512d47f4a4c39 100644 --- a/crates/bevy_picking/src/input.rs +++ b/crates/bevy_picking/src/input.rs @@ -27,7 +27,7 @@ use bevy_window::{PrimaryWindow, WindowEvent, WindowRef}; use tracing::debug; use crate::pointer::{ - Location, PointerAction, PointerButton, PointerId, PointerInput, PointerLocation, + Location, PointerAction, PointerButton, PointerId, PointerInput, PointerKind, PointerLocation, }; use crate::PickSet; @@ -99,7 +99,7 @@ impl Plugin for PointerInputPlugin { /// Spawns the default mouse pointer. pub fn spawn_mouse_pointer(mut commands: Commands) { - commands.spawn(PointerId::Mouse); + commands.spawn(PointerId::MOUSE); } /// Sends mouse pointer events to be processed by the core plugin @@ -126,7 +126,7 @@ pub fn mouse_pick_events( position: event.position, }; pointer_events.send(PointerInput::new( - PointerId::Mouse, + PointerId::MOUSE, location, PointerAction::Move { delta: event.position - *cursor_last, @@ -155,7 +155,7 @@ pub fn mouse_pick_events( ButtonState::Pressed => PointerAction::Press(button), ButtonState::Released => PointerAction::Release(button), }; - pointer_events.send(PointerInput::new(PointerId::Mouse, location, action)); + pointer_events.send(PointerInput::new(PointerId::MOUSE, location, action)); } WindowEvent::MouseWheel(event) => { let MouseWheel { unit, x, y, window } = *event; @@ -172,7 +172,7 @@ pub fn mouse_pick_events( let action = PointerAction::Scroll { x, y, unit }; - pointer_events.send(PointerInput::new(PointerId::Mouse, location, action)); + pointer_events.send(PointerInput::new(PointerId::MOUSE, location, action)); } _ => {} } @@ -192,7 +192,10 @@ pub fn touch_pick_events( ) { for window_event in window_events.read() { if let WindowEvent::TouchInput(touch) = window_event { - let pointer = PointerId::Touch(touch.id); + let pointer = PointerId { + id: touch.id, + kind: PointerKind::Touch, + }; let location = Location { target: match RenderTarget::Window(WindowRef::Entity(touch.window)) .normalize(primary_window.get_single().ok()) diff --git a/crates/bevy_picking/src/pointer.rs b/crates/bevy_picking/src/pointer.rs index dcaaf6060b3f2..5b2a75ec007c6 100644 --- a/crates/bevy_picking/src/pointer.rs +++ b/crates/bevy_picking/src/pointer.rs @@ -16,8 +16,6 @@ use bevy_reflect::prelude::*; use bevy_render::camera::{Camera, NormalizedRenderTarget}; use bevy_window::PrimaryWindow; -use uuid::Uuid; - use core::{fmt::Debug, ops::Deref}; use crate::backend::HitData; @@ -29,41 +27,69 @@ use crate::backend::HitData; #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, Component, Reflect)] #[require(PointerLocation, PointerPress, PointerInteraction)] #[reflect(Component, Default, Debug, Hash, PartialEq)] -pub enum PointerId { - /// The mouse pointer. - #[default] - Mouse, - /// A touch input, usually numbered by window touch events from `winit`. - Touch(u64), - /// A custom, uniquely identified pointer. Useful for mocking inputs or implementing a software - /// controlled cursor. - #[reflect(ignore)] - Custom(Uuid), +pub struct PointerId { + /// A stable identifier for a specific pointer. + /// + /// This is typically provided by winit, + /// and is unique for each touch input or mouse. + pub id: u64, + /// The type of hardware device that created this pointer. + pub kind: PointerKind, } impl PointerId { + /// The [`PointerId`] of the mouse. + /// + /// Currently, only one mouse pointer is supported. + pub const MOUSE: Self = Self { + id: 0, + kind: PointerKind::Mouse, + }; + /// Returns true if the pointer is a touch input. pub fn is_touch(&self) -> bool { - matches!(self, PointerId::Touch(_)) + matches!(self.kind, PointerKind::Touch) } /// Returns true if the pointer is the mouse. pub fn is_mouse(&self) -> bool { - matches!(self, PointerId::Mouse) + matches!(self.kind, PointerKind::Mouse) } - /// Returns true if the pointer is a custom input. - pub fn is_custom(&self) -> bool { - matches!(self, PointerId::Custom(_)) + /// Returns true if the pointer is a virtual input. + pub fn is_virtual(&self) -> bool { + matches!(self.kind, PointerKind::Virtual) } /// Returns the touch id if the pointer is a touch input. pub fn get_touch_id(&self) -> Option { - if let PointerId::Touch(id) = self { - Some(*id) + if let PointerKind::Touch = self.kind { + Some(self.id) } else { None } } } +/// The input device that created a pointer. +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, Reflect)] +#[reflect(Default, Debug, Hash, PartialEq)] +pub enum PointerKind { + /// A pointer that is controlled by a mouse. + /// + /// Not a rodent; the device that you move around on a desk. + Mouse, + /// A pointer that is controlled by a touch input. + /// + /// Typically with your fingers on a touch screen, + /// but can also be a stylus or other touch input device. + Touch, + /// A pointer that is driven by code. + /// + /// No underlying hardware is associated with this pointer, + /// and it might represent a gamepad moving a cursor, + /// or an input sent to a focused element in a UI. + #[default] + Virtual, +} + /// Holds a list of entities this pointer is currently interacting with, sorted from nearest to /// farthest. #[derive(Debug, Default, Clone, Component, Reflect)] diff --git a/examples/ui/directional_navigation.rs b/examples/ui/directional_navigation.rs index 0512c7498db54..970b55bb9ef33 100644 --- a/examples/ui/directional_navigation.rs +++ b/examples/ui/directional_navigation.rs @@ -17,7 +17,7 @@ use bevy::{ math::{CompassOctant, FloatOrd}, picking::{ backend::HitData, - pointer::{Location, PointerId}, + pointer::{Location, PointerId, PointerKind}, }, platform_support::collections::{HashMap, HashSet}, prelude::*, @@ -383,8 +383,10 @@ fn interact_with_focused_button( commands.trigger_targets( Pointer:: { target: focused_entity, - // We're pretending that we're a mouse - pointer_id: PointerId::Mouse, + pointer_id: PointerId { + id: 0, + kind: PointerKind::Virtual, + }, // This field isn't used, so we're just setting it to a placeholder value pointer_location: Location { target: NormalizedRenderTarget::Image(