mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
parent
5df6804daf
commit
a80469bd13
8 changed files with 250 additions and 1 deletions
|
@ -3,6 +3,7 @@
|
|||
## Unreleased
|
||||
|
||||
### Added
|
||||
- [Touch Input][696]
|
||||
- [Do not depend on spirv on wasm32 target][689]
|
||||
- [Another fast compile flag for macOS][552]
|
||||
|
||||
|
@ -15,6 +16,7 @@
|
|||
- Individual color-components must now be accessed through setters and getters: `.r`, `.g`, `.b`, `.a`, `.set_r`, `.set_g`, `.set_b`, `.set_a`, and the corresponding methods with the `*_linear` suffix.
|
||||
- Despawning an entity multiple times causes a debug-level log message to be emitted instead of a panic [649] [651]
|
||||
|
||||
[696]: https://github.com/bevyengine/bevy/pull/696
|
||||
[689]: https://github.com/bevyengine/bevy/pull/689
|
||||
[552]: https://github.com/bevyengine/bevy/pull/552
|
||||
[616]: https://github.com/bevyengine/bevy/pull/616
|
||||
|
|
|
@ -230,6 +230,14 @@ path = "examples/input/keyboard_input_events.rs"
|
|||
name = "gamepad_input"
|
||||
path = "examples/input/gamepad_input.rs"
|
||||
|
||||
[[example]]
|
||||
name = "touch_input"
|
||||
path = "examples/input/touch_input.rs"
|
||||
|
||||
[[example]]
|
||||
name = "touch_input_highlevel"
|
||||
path = "examples/input/touch_input_highlevel.rs"
|
||||
|
||||
[[example]]
|
||||
name = "scene"
|
||||
path = "examples/scene/scene.rs"
|
||||
|
|
|
@ -4,6 +4,7 @@ mod input;
|
|||
pub mod keyboard;
|
||||
pub mod mouse;
|
||||
pub mod system;
|
||||
pub mod touch;
|
||||
|
||||
pub use axis::*;
|
||||
pub use input::*;
|
||||
|
@ -23,6 +24,7 @@ pub mod prelude {
|
|||
use bevy_app::prelude::*;
|
||||
use keyboard::{keyboard_input_system, KeyCode, KeyboardInput};
|
||||
use mouse::{mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion, MouseWheel};
|
||||
use touch::{touch_screen_input_system, TouchInput, Touches};
|
||||
|
||||
use bevy_ecs::IntoQuerySystem;
|
||||
use gamepad::{GamepadAxis, GamepadButton, GamepadEvent};
|
||||
|
@ -50,6 +52,12 @@ impl Plugin for InputPlugin {
|
|||
.add_event::<GamepadEvent>()
|
||||
.init_resource::<Input<GamepadButton>>()
|
||||
.init_resource::<Axis<GamepadAxis>>()
|
||||
.init_resource::<Axis<GamepadButton>>();
|
||||
.init_resource::<Axis<GamepadButton>>()
|
||||
.add_event::<TouchInput>()
|
||||
.init_resource::<Touches>()
|
||||
.add_system_to_stage(
|
||||
bevy_app::stage::EVENT_UPDATE,
|
||||
touch_screen_input_system.system(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
147
crates/bevy_input/src/touch.rs
Normal file
147
crates/bevy_input/src/touch.rs
Normal file
|
@ -0,0 +1,147 @@
|
|||
use bevy_app::{EventReader, Events};
|
||||
use bevy_ecs::{Local, Res, ResMut};
|
||||
use bevy_math::Vec2;
|
||||
use bevy_utils::{HashMap, HashSet};
|
||||
|
||||
/// A touch input event
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TouchInput {
|
||||
pub phase: TouchPhase,
|
||||
pub position: Vec2,
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// Unique identifier of a finger.
|
||||
pub id: u64,
|
||||
}
|
||||
|
||||
/// Describes touch-screen input state.
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum TouchPhase {
|
||||
Started,
|
||||
Moved,
|
||||
Ended,
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TouchSystemState {
|
||||
touch_event_reader: EventReader<TouchInput>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Touch {
|
||||
pub id: u64,
|
||||
pub start_position: Vec2,
|
||||
pub previous_position: Vec2,
|
||||
pub position: Vec2,
|
||||
}
|
||||
|
||||
impl Touch {
|
||||
pub fn delta(&self) -> Vec2 {
|
||||
self.position - self.previous_position
|
||||
}
|
||||
|
||||
pub fn distance(&self) -> Vec2 {
|
||||
self.position - self.start_position
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Touches {
|
||||
active_touches: HashMap<u64, Touch>,
|
||||
just_pressed: HashSet<u64>,
|
||||
just_released: HashSet<u64>,
|
||||
just_cancelled: HashSet<u64>,
|
||||
}
|
||||
|
||||
impl Touches {
|
||||
pub fn iter(&self) -> impl Iterator<Item = &Touch> + '_ {
|
||||
self.active_touches.values()
|
||||
}
|
||||
|
||||
pub fn just_pressed(&self, id: u64) -> bool {
|
||||
self.just_pressed.contains(&id)
|
||||
}
|
||||
|
||||
pub fn iter_just_pressed(&self) -> impl Iterator<Item = &Touch> + '_ {
|
||||
self.just_pressed
|
||||
.iter()
|
||||
.map(move |id| self.active_touches.get(id).unwrap())
|
||||
}
|
||||
|
||||
pub fn just_released(&self, id: u64) -> bool {
|
||||
self.just_released.contains(&id)
|
||||
}
|
||||
|
||||
pub fn iter_just_released(&self) -> impl Iterator<Item = &Touch> + '_ {
|
||||
self.just_released
|
||||
.iter()
|
||||
.map(move |id| self.active_touches.get(id).unwrap())
|
||||
}
|
||||
|
||||
pub fn just_cancelled(&self, id: u64) -> bool {
|
||||
self.just_cancelled.contains(&id)
|
||||
}
|
||||
|
||||
pub fn iter_just_cancelled(&self) -> impl Iterator<Item = &Touch> + '_ {
|
||||
self.just_cancelled
|
||||
.iter()
|
||||
.map(move |id| self.active_touches.get(id).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the Touches resource with the latest TouchInput events
|
||||
pub fn touch_screen_input_system(
|
||||
mut state: Local<TouchSystemState>,
|
||||
mut touch_state: ResMut<Touches>,
|
||||
touch_input_events: Res<Events<TouchInput>>,
|
||||
) {
|
||||
touch_state.just_pressed.clear();
|
||||
|
||||
let released_touch_ids: HashSet<_> = touch_state.just_released.iter().cloned().collect();
|
||||
let cancelled_touch_ids: HashSet<_> = touch_state.just_released.iter().cloned().collect();
|
||||
|
||||
touch_state.just_released.clear();
|
||||
touch_state.just_cancelled.clear();
|
||||
|
||||
for released_id in released_touch_ids {
|
||||
touch_state.active_touches.remove(&released_id);
|
||||
}
|
||||
|
||||
for cancelled_id in cancelled_touch_ids {
|
||||
touch_state.active_touches.remove(&cancelled_id);
|
||||
}
|
||||
|
||||
for event in state.touch_event_reader.iter(&touch_input_events) {
|
||||
let active_touch = touch_state.active_touches.get(&event.id);
|
||||
match event.phase {
|
||||
TouchPhase::Started => {
|
||||
touch_state.active_touches.insert(
|
||||
event.id,
|
||||
Touch {
|
||||
id: event.id,
|
||||
start_position: event.position,
|
||||
previous_position: event.position,
|
||||
position: event.position,
|
||||
},
|
||||
);
|
||||
touch_state.just_pressed.insert(event.id);
|
||||
}
|
||||
TouchPhase::Moved => {
|
||||
let old_touch = active_touch.unwrap();
|
||||
let mut new_touch = old_touch.clone();
|
||||
new_touch.previous_position = new_touch.position;
|
||||
new_touch.position = event.position;
|
||||
touch_state.active_touches.insert(event.id, new_touch);
|
||||
}
|
||||
TouchPhase::Ended => {
|
||||
touch_state.just_released.insert(event.id);
|
||||
}
|
||||
TouchPhase::Cancelled => {
|
||||
touch_state.just_cancelled.insert(event.id);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
use bevy_input::{
|
||||
keyboard::{ElementState, KeyCode, KeyboardInput},
|
||||
mouse::MouseButton,
|
||||
touch::{TouchInput, TouchPhase},
|
||||
};
|
||||
use bevy_math::Vec2;
|
||||
|
||||
pub fn convert_keyboard_input(keyboard_input: &winit::event::KeyboardInput) -> KeyboardInput {
|
||||
KeyboardInput {
|
||||
|
@ -27,6 +29,19 @@ pub fn convert_mouse_button(mouse_button: winit::event::MouseButton) -> MouseBut
|
|||
}
|
||||
}
|
||||
|
||||
pub fn convert_touch_input(touch_input: winit::event::Touch) -> TouchInput {
|
||||
TouchInput {
|
||||
phase: match touch_input.phase {
|
||||
winit::event::TouchPhase::Started => TouchPhase::Started,
|
||||
winit::event::TouchPhase::Moved => TouchPhase::Moved,
|
||||
winit::event::TouchPhase::Ended => TouchPhase::Ended,
|
||||
winit::event::TouchPhase::Cancelled => TouchPhase::Cancelled,
|
||||
},
|
||||
position: Vec2::new(touch_input.location.x as f32, touch_input.location.y as f32),
|
||||
id: touch_input.id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_virtual_key_code(virtual_key_code: winit::event::VirtualKeyCode) -> KeyCode {
|
||||
match virtual_key_code {
|
||||
winit::event::VirtualKeyCode::Key1 => KeyCode::Key1,
|
||||
|
|
|
@ -4,6 +4,7 @@ mod winit_windows;
|
|||
use bevy_input::{
|
||||
keyboard::KeyboardInput,
|
||||
mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
|
||||
touch::TouchInput,
|
||||
};
|
||||
pub use winit_config::*;
|
||||
pub use winit_windows::*;
|
||||
|
@ -258,6 +259,11 @@ pub fn winit_runner(mut app: App) {
|
|||
});
|
||||
}
|
||||
},
|
||||
WindowEvent::Touch(touch) => {
|
||||
let mut touch_input_events =
|
||||
app.resources.get_mut::<Events<TouchInput>>().unwrap();
|
||||
touch_input_events.send(converters::convert_touch_input(touch));
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
event::Event::DeviceEvent { ref event, .. } => {
|
||||
|
|
35
examples/input/touch_input.rs
Normal file
35
examples/input/touch_input.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
use bevy::{input::touch::*, prelude::*};
|
||||
|
||||
fn main() {
|
||||
App::build()
|
||||
.add_default_plugins()
|
||||
.add_system(touch_system.system())
|
||||
.run();
|
||||
}
|
||||
|
||||
fn touch_system(touches: Res<Touches>) {
|
||||
for touch in touches.iter() {
|
||||
println!(
|
||||
"active touch: {} {} {} {}",
|
||||
touch.id, touch.position, touch.previous_position, touch.start_position
|
||||
);
|
||||
|
||||
if touches.just_pressed(touch.id) {
|
||||
println!(
|
||||
"just pressed touch with id: {:?}, at: {:?}",
|
||||
touch.id, touch.position
|
||||
);
|
||||
}
|
||||
|
||||
if touches.just_released(touch.id) {
|
||||
println!(
|
||||
"just released touch with id: {:?}, at: {:?}",
|
||||
touch.id, touch.position
|
||||
);
|
||||
}
|
||||
|
||||
if touches.just_cancelled(touch.id) {
|
||||
println!("cancelled touch with id: {:?}", touch.id);
|
||||
}
|
||||
}
|
||||
}
|
28
examples/input/touch_input_highlevel.rs
Normal file
28
examples/input/touch_input_highlevel.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use bevy::{input::touch::*, prelude::*};
|
||||
|
||||
fn main() {
|
||||
App::build()
|
||||
.add_default_plugins()
|
||||
.add_system(touch_system.system())
|
||||
.run();
|
||||
}
|
||||
|
||||
fn touch_system(touches: Res<Touches>) {
|
||||
for touch in touches.iter_just_pressed() {
|
||||
println!(
|
||||
"just pressed touch with id: {:?}, at: {:?}",
|
||||
touch.id, touch.position
|
||||
);
|
||||
}
|
||||
|
||||
for touch in touches.iter_just_released() {
|
||||
println!(
|
||||
"just released touch with id: {:?}, at: {:?}",
|
||||
touch.id, touch.position
|
||||
);
|
||||
}
|
||||
|
||||
for touch in touches.iter_just_cancelled() {
|
||||
println!("cancelled touch with id: {:?}", touch.id);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue