From df90e44b59b7146039326f40177d93019ffb5c66 Mon Sep 17 00:00:00 2001 From: Clinton Selke Date: Fri, 26 Jan 2024 15:12:08 +1000 Subject: [PATCH 1/2] support both touch and mouse on same target platform --- src/input.rs | 52 ++++++++++++++++++++++++++++++++--------------- src/lib.rs | 8 +++----- src/ui/bundles.rs | 3 ++- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/input.rs b/src/input.rs index 51af182..3c396df 100644 --- a/src/input.rs +++ b/src/input.rs @@ -10,15 +10,18 @@ use crate::{ VirtualJoystickType, }; -#[derive(Event)] -pub enum InputEvent { - StartDrag { id: u64, pos: Vec2 }, - Dragging { id: u64, pos: Vec2 }, - EndDrag { id: u64, pos: Vec2 }, +#[derive(Clone, Copy, Debug, Default, Reflect, PartialEq, Eq)] +pub enum TouchOrMouse { + #[default] + Touch, + Mouse, } -pub fn run_if_pc() -> bool { - !["android", "ios"].contains(&std::env::consts::OS) +#[derive(Event)] +pub enum InputEvent { + StartDrag { id: u64, pos: Vec2, touch_or_mouse: TouchOrMouse }, + Dragging { id: u64, pos: Vec2, touch_or_mouse: TouchOrMouse }, + EndDrag { id: u64, pos: Vec2, touch_or_mouse: TouchOrMouse }, } fn is_some_and(opt: Option, cb: impl FnOnce(T) -> bool) -> bool { @@ -49,7 +52,12 @@ pub fn update_input( } for event in &input_events { match event { - InputEvent::StartDrag { id, pos } => { + InputEvent::StartDrag { id, pos, touch_or_mouse } => { + if let Some(current_interaction_touch_or_mouse) = &knob.current_interaction_touch_or_mouse { + if *current_interaction_touch_or_mouse != *touch_or_mouse { + continue; + } + } if knob.interactable_zone_rect.contains(*pos) && knob.id_drag.is_none() || is_some_and(knob.id_drag, |i| i != *id) && knob.interactable_zone_rect.contains(*pos) @@ -58,6 +66,7 @@ pub fn update_input( knob.start_pos = *pos; knob.current_pos = *pos; knob.delta = Vec2::ZERO; + knob.current_interaction_touch_or_mouse = Some(*touch_or_mouse); send_values.send(VirtualJoystickEvent { id: node.id.clone(), event: VirtualJoystickEventType::Press, @@ -67,7 +76,12 @@ pub fn update_input( }); } } - InputEvent::Dragging { id, pos } => { + InputEvent::Dragging { id, pos, touch_or_mouse } => { + if let Some(current_interaction_touch_or_mouse) = &knob.current_interaction_touch_or_mouse { + if *current_interaction_touch_or_mouse != *touch_or_mouse { + continue; + } + } if !is_some_and(knob.id_drag, |i| i == *id) { continue; } @@ -88,7 +102,12 @@ pub fn update_input( d.y.signum() * d.y.abs().min(1.), ); } - InputEvent::EndDrag { id, pos: _ } => { + InputEvent::EndDrag { id, pos: _, touch_or_mouse } => { + if let Some(current_interaction_touch_or_mouse) = &knob.current_interaction_touch_or_mouse { + if *current_interaction_touch_or_mouse != *touch_or_mouse { + continue; + } + } if !is_some_and(knob.id_drag, |i| i == *id) { continue; } @@ -97,6 +116,7 @@ pub fn update_input( knob.start_pos = Vec2::ZERO; knob.current_pos = Vec2::ZERO; knob.delta = Vec2::ZERO; + knob.current_interaction_touch_or_mouse = None; send_values.send(VirtualJoystickEvent { id: node.id.clone(), event: VirtualJoystickEventType::Up, @@ -136,15 +156,15 @@ pub fn update_joystick( match phase { // Start drag TouchPhase::Started => { - send_values.send(InputEvent::StartDrag { id: *id, pos: *pos }); + send_values.send(InputEvent::StartDrag { id: *id, pos: *pos, touch_or_mouse: TouchOrMouse::Touch }); } // Dragging TouchPhase::Moved => { - send_values.send(InputEvent::Dragging { id: *id, pos: *pos }); + send_values.send(InputEvent::Dragging { id: *id, pos: *pos, touch_or_mouse: TouchOrMouse::Touch }); } // End drag TouchPhase::Ended | TouchPhase::Canceled => { - send_values.send(InputEvent::EndDrag { id: *id, pos: *pos }); + send_values.send(InputEvent::EndDrag { id: *id, pos: *pos, touch_or_mouse: TouchOrMouse::Touch }); } } } @@ -162,17 +182,17 @@ pub fn update_joystick_by_mouse( for mousebtn in mousebtn_evr.read() { // End drag if mousebtn.button == MouseButton::Left && mousebtn.state == ButtonState::Released { - send_values.send(InputEvent::EndDrag { id: 0, pos }); + send_values.send(InputEvent::EndDrag { id: 0, pos, touch_or_mouse: TouchOrMouse::Mouse }); } // Start drag if mousebtn.button == MouseButton::Left && mousebtn.state == ButtonState::Pressed { - send_values.send(InputEvent::StartDrag { id: 0, pos }); + send_values.send(InputEvent::StartDrag { id: 0, pos, touch_or_mouse: TouchOrMouse::Mouse }); } } // Dragging if mouse_button_input.pressed(MouseButton::Left) { - send_values.send(InputEvent::Dragging { id: 0, pos }); + send_values.send(InputEvent::Dragging { id: 0, pos, touch_or_mouse: TouchOrMouse::Mouse }); } } diff --git a/src/lib.rs b/src/lib.rs index 5eb1ff3..1d8102e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,7 @@ mod ui; mod utils; pub use behaviour::{VirtualJoystickAxis, VirtualJoystickType}; -use input::{run_if_pc, update_input, update_joystick, update_joystick_by_mouse, InputEvent}; +use input::{update_input, update_joystick, update_joystick_by_mouse, InputEvent}; pub use ui::{ VirtualJoystickBundle, VirtualJoystickInteractionArea, VirtualJoystickNode, VirtualJoystickUIBackground, VirtualJoystickUIKnob, @@ -50,14 +50,12 @@ impl Plugin for VirtualJoystickPlugin { .add_systems( PreUpdate, update_joystick - .before(update_input::) - .run_if(not(run_if_pc)), + .before(update_input::), ) .add_systems( PreUpdate, update_joystick_by_mouse - .before(update_input::) - .run_if(run_if_pc), + .before(update_input::), ) .add_systems(PreUpdate, update_input::) .add_systems( diff --git a/src/ui/bundles.rs b/src/ui/bundles.rs index 520b4ad..0b8f8a8 100644 --- a/src/ui/bundles.rs +++ b/src/ui/bundles.rs @@ -3,7 +3,7 @@ use bevy::{prelude::*, ui::RelativeCursorPosition}; #[cfg(feature = "inspect")] use bevy_inspector_egui::prelude::*; -use crate::{VirtualJoystickAxis, VirtualJoystickID, VirtualJoystickType}; +use crate::{input::TouchOrMouse, VirtualJoystickAxis, VirtualJoystickID, VirtualJoystickType}; #[derive(Component, Clone, Debug, Default, Reflect)] #[reflect(Component, Default)] @@ -70,6 +70,7 @@ pub struct VirtualJoystickData { pub current_pos: Vec2, pub delta: Vec2, pub interactable_zone_rect: Rect, + pub current_interaction_touch_or_mouse: Option, } impl VirtualJoystickBundle { From 22ff52aadcc88edee3cfb37009909cd11487a10a Mon Sep 17 00:00:00 2001 From: Clinton Selke Date: Fri, 26 Jan 2024 16:48:58 +1000 Subject: [PATCH 2/2] using boolean is_mouse instead of 2 varient enum TouchOrMouse --- src/input.rs | 75 ++++++++++++++++++++++++++++++----------------- src/lib.rs | 9 ++---- src/ui/bundles.rs | 7 +++-- 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/input.rs b/src/input.rs index 3c396df..e1ce94a 100644 --- a/src/input.rs +++ b/src/input.rs @@ -10,18 +10,11 @@ use crate::{ VirtualJoystickType, }; -#[derive(Clone, Copy, Debug, Default, Reflect, PartialEq, Eq)] -pub enum TouchOrMouse { - #[default] - Touch, - Mouse, -} - #[derive(Event)] pub enum InputEvent { - StartDrag { id: u64, pos: Vec2, touch_or_mouse: TouchOrMouse }, - Dragging { id: u64, pos: Vec2, touch_or_mouse: TouchOrMouse }, - EndDrag { id: u64, pos: Vec2, touch_or_mouse: TouchOrMouse }, + StartDrag { id: u64, pos: Vec2, is_mouse: bool }, + Dragging { id: u64, pos: Vec2, is_mouse: bool }, + EndDrag { id: u64, pos: Vec2, is_mouse: bool }, } fn is_some_and(opt: Option, cb: impl FnOnce(T) -> bool) -> bool { @@ -52,9 +45,9 @@ pub fn update_input( } for event in &input_events { match event { - InputEvent::StartDrag { id, pos, touch_or_mouse } => { - if let Some(current_interaction_touch_or_mouse) = &knob.current_interaction_touch_or_mouse { - if *current_interaction_touch_or_mouse != *touch_or_mouse { + InputEvent::StartDrag { id, pos, is_mouse } => { + if let Some(current_iteraction_is_mouse) = &knob.current_iteraction_is_mouse { + if *current_iteraction_is_mouse != *is_mouse { continue; } } @@ -66,7 +59,7 @@ pub fn update_input( knob.start_pos = *pos; knob.current_pos = *pos; knob.delta = Vec2::ZERO; - knob.current_interaction_touch_or_mouse = Some(*touch_or_mouse); + knob.current_iteraction_is_mouse = Some(*is_mouse); send_values.send(VirtualJoystickEvent { id: node.id.clone(), event: VirtualJoystickEventType::Press, @@ -76,9 +69,9 @@ pub fn update_input( }); } } - InputEvent::Dragging { id, pos, touch_or_mouse } => { - if let Some(current_interaction_touch_or_mouse) = &knob.current_interaction_touch_or_mouse { - if *current_interaction_touch_or_mouse != *touch_or_mouse { + InputEvent::Dragging { id, pos, is_mouse } => { + if let Some(current_iteraction_is_mouse) = &knob.current_iteraction_is_mouse { + if *current_iteraction_is_mouse != *is_mouse { continue; } } @@ -102,9 +95,13 @@ pub fn update_input( d.y.signum() * d.y.abs().min(1.), ); } - InputEvent::EndDrag { id, pos: _, touch_or_mouse } => { - if let Some(current_interaction_touch_or_mouse) = &knob.current_interaction_touch_or_mouse { - if *current_interaction_touch_or_mouse != *touch_or_mouse { + InputEvent::EndDrag { + id, + pos: _, + is_mouse, + } => { + if let Some(current_iteraction_is_mouse) = &knob.current_iteraction_is_mouse { + if *current_iteraction_is_mouse != *is_mouse { continue; } } @@ -116,7 +113,7 @@ pub fn update_input( knob.start_pos = Vec2::ZERO; knob.current_pos = Vec2::ZERO; knob.delta = Vec2::ZERO; - knob.current_interaction_touch_or_mouse = None; + knob.current_iteraction_is_mouse = None; send_values.send(VirtualJoystickEvent { id: node.id.clone(), event: VirtualJoystickEventType::Up, @@ -156,15 +153,27 @@ pub fn update_joystick( match phase { // Start drag TouchPhase::Started => { - send_values.send(InputEvent::StartDrag { id: *id, pos: *pos, touch_or_mouse: TouchOrMouse::Touch }); + send_values.send(InputEvent::StartDrag { + id: *id, + pos: *pos, + is_mouse: false, + }); } // Dragging TouchPhase::Moved => { - send_values.send(InputEvent::Dragging { id: *id, pos: *pos, touch_or_mouse: TouchOrMouse::Touch }); + send_values.send(InputEvent::Dragging { + id: *id, + pos: *pos, + is_mouse: false, + }); } // End drag TouchPhase::Ended | TouchPhase::Canceled => { - send_values.send(InputEvent::EndDrag { id: *id, pos: *pos, touch_or_mouse: TouchOrMouse::Touch }); + send_values.send(InputEvent::EndDrag { + id: *id, + pos: *pos, + is_mouse: false, + }); } } } @@ -182,17 +191,29 @@ pub fn update_joystick_by_mouse( for mousebtn in mousebtn_evr.read() { // End drag if mousebtn.button == MouseButton::Left && mousebtn.state == ButtonState::Released { - send_values.send(InputEvent::EndDrag { id: 0, pos, touch_or_mouse: TouchOrMouse::Mouse }); + send_values.send(InputEvent::EndDrag { + id: 0, + pos, + is_mouse: true, + }); } // Start drag if mousebtn.button == MouseButton::Left && mousebtn.state == ButtonState::Pressed { - send_values.send(InputEvent::StartDrag { id: 0, pos, touch_or_mouse: TouchOrMouse::Mouse }); + send_values.send(InputEvent::StartDrag { + id: 0, + pos, + is_mouse: true, + }); } } // Dragging if mouse_button_input.pressed(MouseButton::Left) { - send_values.send(InputEvent::Dragging { id: 0, pos, touch_or_mouse: TouchOrMouse::Mouse }); + send_values.send(InputEvent::Dragging { + id: 0, + pos, + is_mouse: true, + }); } } diff --git a/src/lib.rs b/src/lib.rs index 1d8102e..85c8222 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,15 +47,10 @@ impl Plugin for VirtualJoystickPlugin { .register_type::() .add_event::>() .add_event::() + .add_systems(PreUpdate, update_joystick.before(update_input::)) .add_systems( PreUpdate, - update_joystick - .before(update_input::), - ) - .add_systems( - PreUpdate, - update_joystick_by_mouse - .before(update_input::), + update_joystick_by_mouse.before(update_input::), ) .add_systems(PreUpdate, update_input::) .add_systems( diff --git a/src/ui/bundles.rs b/src/ui/bundles.rs index 0b8f8a8..a29f02b 100644 --- a/src/ui/bundles.rs +++ b/src/ui/bundles.rs @@ -3,7 +3,7 @@ use bevy::{prelude::*, ui::RelativeCursorPosition}; #[cfg(feature = "inspect")] use bevy_inspector_egui::prelude::*; -use crate::{input::TouchOrMouse, VirtualJoystickAxis, VirtualJoystickID, VirtualJoystickType}; +use crate::{VirtualJoystickAxis, VirtualJoystickID, VirtualJoystickType}; #[derive(Component, Clone, Debug, Default, Reflect)] #[reflect(Component, Default)] @@ -70,7 +70,10 @@ pub struct VirtualJoystickData { pub current_pos: Vec2, pub delta: Vec2, pub interactable_zone_rect: Rect, - pub current_interaction_touch_or_mouse: Option, + /// None means no current interaction
+ /// Some(false) means current interaction is touch
+ /// Some(true) means current interaction is mouse + pub current_iteraction_is_mouse: Option, } impl VirtualJoystickBundle {