From 1a381e65f953e50b78b554fe1ce36f6d10346125 Mon Sep 17 00:00:00 2001 From: Tom Bebbington Date: Mon, 24 Aug 2020 21:11:21 +0100 Subject: [PATCH 1/3] Implement touch support --- Cargo.toml | 8 +++++ crates/bevy_input/src/lib.rs | 12 ++++++- crates/bevy_input/src/touch.rs | 52 ++++++++++++++++++++++++++++ crates/bevy_winit/src/converters.rs | 10 ++++++ crates/bevy_winit/src/lib.rs | 23 ++++++++++-- examples/input/touch_input.rs | 23 ++++++++++++ examples/input/touch_input_events.rs | 36 +++++++++++++++++++ 7 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 crates/bevy_input/src/touch.rs create mode 100644 examples/input/touch_input.rs create mode 100644 examples/input/touch_input_events.rs diff --git a/Cargo.toml b/Cargo.toml index dd7e8d1d72108..5af936093ed77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -185,6 +185,14 @@ path = "examples/input/keyboard_input.rs" name = "keyboard_input_events" path = "examples/input/keyboard_input_events.rs" +[[example]] +name = "touch_input" +path = "examples/input/touch_input.rs" + +[[example]] +name = "touch_input_events" +path = "examples/input/touch_input_events.rs" + [[example]] name = "scene" path = "examples/scene/scene.rs" diff --git a/crates/bevy_input/src/lib.rs b/crates/bevy_input/src/lib.rs index 1893d86b8ac28..2b384fe61e14a 100644 --- a/crates/bevy_input/src/lib.rs +++ b/crates/bevy_input/src/lib.rs @@ -1,17 +1,19 @@ mod input; pub mod keyboard; pub mod mouse; +pub mod touch; pub mod system; pub use input::*; pub mod prelude { - pub use crate::{keyboard::KeyCode, mouse::MouseButton, Input}; + pub use crate::{keyboard::KeyCode, mouse::MouseButton, touch::Finger, Input}; } use bevy_app::prelude::*; use keyboard::{keyboard_input_system, KeyCode, KeyboardInput}; use mouse::{mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion, MouseWheel}; +use touch::{touch_finger_input_system, Finger, TouchFingerInput, TouchMotion}; use bevy_ecs::IntoQuerySystem; @@ -25,6 +27,9 @@ impl Plugin for InputPlugin { .add_event::() .add_event::() .add_event::() + .add_event::() + .add_event::() + .add_event::() .init_resource::>() .add_system_to_stage( bevy_app::stage::EVENT_UPDATE, @@ -34,6 +39,11 @@ impl Plugin for InputPlugin { .add_system_to_stage( bevy_app::stage::EVENT_UPDATE, mouse_button_input_system.system(), + ) + .init_resource::>() + .add_system_to_stage( + bevy_app::stage::EVENT_UPDATE, + touch_finger_input_system.system(), ); } } diff --git a/crates/bevy_input/src/touch.rs b/crates/bevy_input/src/touch.rs new file mode 100644 index 0000000000000..39b441744e801 --- /dev/null +++ b/crates/bevy_input/src/touch.rs @@ -0,0 +1,52 @@ +use super::keyboard::ElementState; +use crate::Input; +use bevy_app::prelude::{EventReader, Events}; +use bevy_ecs::{Local, Res, ResMut}; +use bevy_math::Vec2; + + +/// A finger on a touch screen device +#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] +pub struct Finger(pub u64); + +/// A finger pressed event +#[derive(Debug, Clone)] +pub struct TouchFingerInput { + pub finger: Finger, + pub state: ElementState, + pub position: Vec2 +} + + +/// A finer motion event +#[derive(Debug, Clone)] +pub struct TouchMotion { + pub finger: Finger, + pub position: Vec2 +} + + +/// State used by the mouse button input system +#[derive(Default)] +pub struct TouchFingerInputState { + touch_finger_input_event_reader: EventReader, +} + +/// Updates the Input resource with the latest TouchFingerInput events +pub fn touch_finger_input_system( + mut state: Local, + mut touch_finger_input: ResMut>, + touch_finger_input_events: Res>, +) { + touch_finger_input.update(); + for event in state + .touch_finger_input_event_reader + .iter(&touch_finger_input_events) + { + match event.state { + ElementState::Pressed => touch_finger_input.press(event.finger), + ElementState::Released => touch_finger_input.release(event.finger), + } + } +} diff --git a/crates/bevy_winit/src/converters.rs b/crates/bevy_winit/src/converters.rs index 3014da2d431bf..aebda2f90617c 100644 --- a/crates/bevy_winit/src/converters.rs +++ b/crates/bevy_winit/src/converters.rs @@ -1,7 +1,9 @@ use bevy_input::{ keyboard::{ElementState, KeyCode, KeyboardInput}, mouse::MouseButton, + touch::{TouchFingerInput, Finger} }; +use bevy_math::Vec2; pub fn convert_keyboard_input(keyboard_input: &winit::event::KeyboardInput) -> KeyboardInput { KeyboardInput { @@ -192,3 +194,11 @@ pub fn convert_virtual_key_code(virtual_key_code: winit::event::VirtualKeyCode) winit::event::VirtualKeyCode::Cut => KeyCode::Cut, } } + +pub fn convert_touch_input(state: ElementState, touch: &winit::event::Touch) -> TouchFingerInput { + TouchFingerInput { + finger: Finger(touch.id), + state, + position: Vec2::new(touch.location.x as f32, touch.location.y as f32) + } +} \ No newline at end of file diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index b6261ae866985..67d166ffb683a 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -2,8 +2,9 @@ mod converters; mod winit_config; mod winit_windows; use bevy_input::{ - keyboard::KeyboardInput, + keyboard::{ElementState, KeyboardInput}, mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel}, + touch::{TouchFingerInput, Finger, TouchMotion} }; pub use winit_config::*; pub use winit_windows::*; @@ -17,7 +18,7 @@ use bevy_window::{ use event::Event; use winit::{ event, - event::{DeviceEvent, WindowEvent}, + event::{DeviceEvent, WindowEvent, TouchPhase, Touch}, event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget}, }; @@ -192,6 +193,24 @@ pub fn winit_runner(mut app: App) { }); } }, + WindowEvent::Touch (touch @ Touch {phase: TouchPhase::Started, ..}) => { + let mut touch_finger_input_events = + app.resources.get_mut::>().unwrap(); + touch_finger_input_events.send(converters::convert_touch_input(ElementState::Pressed, &touch)); + }, + WindowEvent::Touch (touch @ Touch {phase: TouchPhase::Ended, ..}) => { + let mut touch_finger_input_events = + app.resources.get_mut::>().unwrap(); + touch_finger_input_events.send(converters::convert_touch_input(ElementState::Released, &touch)); + }, + WindowEvent::Touch (Touch {phase: TouchPhase::Moved, id, location, ..}) => { + let mut touch_finger_moved_events = + app.resources.get_mut::>().unwrap(); + touch_finger_moved_events.send(TouchMotion { + finger: Finger(id), + position: Vec2::new(location.x as f32, location.y as f32) + }); + }, _ => {} }, event::Event::DeviceEvent { ref event, .. } => { diff --git a/examples/input/touch_input.rs b/examples/input/touch_input.rs new file mode 100644 index 0000000000000..3d30bc28fe266 --- /dev/null +++ b/examples/input/touch_input.rs @@ -0,0 +1,23 @@ +use bevy::prelude::*; + +fn main() { + App::build() + .add_default_plugins() + .add_system(touch_system.system()) + .run(); +} + +// This system prints messages when you use the touchscreen +fn touch_system(finger_input: Res>) { + if finger_input.pressed(Finger(0)) { + println!("finger 0 pressed"); + } + + if finger_input.just_pressed(Finger(0)) { + println!("finger 0 just pressed"); + } + + if finger_input.just_released(Finger(0)) { + println!("finger 0 just released"); + } +} diff --git a/examples/input/touch_input_events.rs b/examples/input/touch_input_events.rs new file mode 100644 index 0000000000000..be392c9a6ca6d --- /dev/null +++ b/examples/input/touch_input_events.rs @@ -0,0 +1,36 @@ +use bevy::{ + input::touch::{TouchFingerInput, TouchMotion}, + prelude::* +}; + +fn main() { + App::build() + .add_default_plugins() + .init_resource::() + .add_system(print_touch_events_system.system()) + .run(); +} + +#[derive(Default)] +struct State { + touch_finger_event_reader: EventReader, + touch_motion_event_reader: EventReader +} + +/// This system prints out all touch events as they come in +fn print_touch_events_system( + mut state: ResMut, + touch_finger_input_events: Res>, + touch_motion_events: Res> +) { + for event in state + .touch_finger_event_reader + .iter(&touch_finger_input_events) + { + println!("{:?}", event); + } + + for event in state.touch_motion_event_reader.iter(&touch_motion_events) { + println!("{:?}", event); + } +} From cec4b69f5483589ab05644ba01e132bf71ea4fe9 Mon Sep 17 00:00:00 2001 From: Tom Bebbington Date: Mon, 24 Aug 2020 21:20:54 +0100 Subject: [PATCH 2/3] Handle touch cancelled event --- crates/bevy_winit/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index 67d166ffb683a..c734635aa8cf5 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -203,6 +203,11 @@ pub fn winit_runner(mut app: App) { app.resources.get_mut::>().unwrap(); touch_finger_input_events.send(converters::convert_touch_input(ElementState::Released, &touch)); }, + WindowEvent::Touch (touch @ Touch {phase: TouchPhase::Cancelled, ..}) => { + let mut touch_finger_input_events = + app.resources.get_mut::>().unwrap(); + touch_finger_input_events.send(converters::convert_touch_input(ElementState::Released, &touch)); + }, WindowEvent::Touch (Touch {phase: TouchPhase::Moved, id, location, ..}) => { let mut touch_finger_moved_events = app.resources.get_mut::>().unwrap(); From bcdafb74f15c08bb16fc3702677bb73dd1dbd149 Mon Sep 17 00:00:00 2001 From: Tom Bebbington Date: Mon, 24 Aug 2020 21:42:01 +0100 Subject: [PATCH 3/3] Format files for CI pass --- crates/bevy_input/src/lib.rs | 2 +- crates/bevy_input/src/touch.rs | 7 +--- crates/bevy_winit/src/converters.rs | 6 +-- crates/bevy_winit/src/lib.rs | 63 +++++++++++++++++++++------- examples/input/touch_input_events.rs | 6 +-- 5 files changed, 58 insertions(+), 26 deletions(-) diff --git a/crates/bevy_input/src/lib.rs b/crates/bevy_input/src/lib.rs index 2b384fe61e14a..a1abe06d76fe3 100644 --- a/crates/bevy_input/src/lib.rs +++ b/crates/bevy_input/src/lib.rs @@ -1,8 +1,8 @@ mod input; pub mod keyboard; pub mod mouse; -pub mod touch; pub mod system; +pub mod touch; pub use input::*; diff --git a/crates/bevy_input/src/touch.rs b/crates/bevy_input/src/touch.rs index 39b441744e801..f4a46f7a0a210 100644 --- a/crates/bevy_input/src/touch.rs +++ b/crates/bevy_input/src/touch.rs @@ -4,7 +4,6 @@ use bevy_app::prelude::{EventReader, Events}; use bevy_ecs::{Local, Res, ResMut}; use bevy_math::Vec2; - /// A finger on a touch screen device #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] @@ -15,18 +14,16 @@ pub struct Finger(pub u64); pub struct TouchFingerInput { pub finger: Finger, pub state: ElementState, - pub position: Vec2 + pub position: Vec2, } - /// A finer motion event #[derive(Debug, Clone)] pub struct TouchMotion { pub finger: Finger, - pub position: Vec2 + pub position: Vec2, } - /// State used by the mouse button input system #[derive(Default)] pub struct TouchFingerInputState { diff --git a/crates/bevy_winit/src/converters.rs b/crates/bevy_winit/src/converters.rs index aebda2f90617c..54f86d7dee3e5 100644 --- a/crates/bevy_winit/src/converters.rs +++ b/crates/bevy_winit/src/converters.rs @@ -1,7 +1,7 @@ use bevy_input::{ keyboard::{ElementState, KeyCode, KeyboardInput}, mouse::MouseButton, - touch::{TouchFingerInput, Finger} + touch::{Finger, TouchFingerInput}, }; use bevy_math::Vec2; @@ -199,6 +199,6 @@ pub fn convert_touch_input(state: ElementState, touch: &winit::event::Touch) -> TouchFingerInput { finger: Finger(touch.id), state, - position: Vec2::new(touch.location.x as f32, touch.location.y as f32) + position: Vec2::new(touch.location.x as f32, touch.location.y as f32), } -} \ No newline at end of file +} diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index c734635aa8cf5..48496e5674d34 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -4,7 +4,7 @@ mod winit_windows; use bevy_input::{ keyboard::{ElementState, KeyboardInput}, mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel}, - touch::{TouchFingerInput, Finger, TouchMotion} + touch::{Finger, TouchFingerInput, TouchMotion}, }; pub use winit_config::*; pub use winit_windows::*; @@ -18,7 +18,7 @@ use bevy_window::{ use event::Event; use winit::{ event, - event::{DeviceEvent, WindowEvent, TouchPhase, Touch}, + event::{DeviceEvent, Touch, TouchPhase, WindowEvent}, event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget}, }; @@ -193,29 +193,64 @@ pub fn winit_runner(mut app: App) { }); } }, - WindowEvent::Touch (touch @ Touch {phase: TouchPhase::Started, ..}) => { + WindowEvent::Touch( + touch + @ + Touch { + phase: TouchPhase::Started, + .. + }, + ) => { let mut touch_finger_input_events = app.resources.get_mut::>().unwrap(); - touch_finger_input_events.send(converters::convert_touch_input(ElementState::Pressed, &touch)); - }, - WindowEvent::Touch (touch @ Touch {phase: TouchPhase::Ended, ..}) => { + touch_finger_input_events.send(converters::convert_touch_input( + ElementState::Pressed, + &touch, + )); + } + WindowEvent::Touch( + touch + @ + Touch { + phase: TouchPhase::Ended, + .. + }, + ) => { let mut touch_finger_input_events = app.resources.get_mut::>().unwrap(); - touch_finger_input_events.send(converters::convert_touch_input(ElementState::Released, &touch)); - }, - WindowEvent::Touch (touch @ Touch {phase: TouchPhase::Cancelled, ..}) => { + touch_finger_input_events.send(converters::convert_touch_input( + ElementState::Released, + &touch, + )); + } + WindowEvent::Touch( + touch + @ + Touch { + phase: TouchPhase::Cancelled, + .. + }, + ) => { let mut touch_finger_input_events = app.resources.get_mut::>().unwrap(); - touch_finger_input_events.send(converters::convert_touch_input(ElementState::Released, &touch)); - }, - WindowEvent::Touch (Touch {phase: TouchPhase::Moved, id, location, ..}) => { + touch_finger_input_events.send(converters::convert_touch_input( + ElementState::Released, + &touch, + )); + } + WindowEvent::Touch(Touch { + phase: TouchPhase::Moved, + id, + location, + .. + }) => { let mut touch_finger_moved_events = app.resources.get_mut::>().unwrap(); touch_finger_moved_events.send(TouchMotion { finger: Finger(id), - position: Vec2::new(location.x as f32, location.y as f32) + position: Vec2::new(location.x as f32, location.y as f32), }); - }, + } _ => {} }, event::Event::DeviceEvent { ref event, .. } => { diff --git a/examples/input/touch_input_events.rs b/examples/input/touch_input_events.rs index be392c9a6ca6d..e3cad65bf84fc 100644 --- a/examples/input/touch_input_events.rs +++ b/examples/input/touch_input_events.rs @@ -1,6 +1,6 @@ use bevy::{ input::touch::{TouchFingerInput, TouchMotion}, - prelude::* + prelude::*, }; fn main() { @@ -14,14 +14,14 @@ fn main() { #[derive(Default)] struct State { touch_finger_event_reader: EventReader, - touch_motion_event_reader: EventReader + touch_motion_event_reader: EventReader, } /// This system prints out all touch events as they come in fn print_touch_events_system( mut state: ResMut, touch_finger_input_events: Res>, - touch_motion_events: Res> + touch_motion_events: Res>, ) { for event in state .touch_finger_event_reader