keyboard input events

This commit is contained in:
Carter Anderson 2020-04-04 14:59:49 -07:00
parent 4c3af427e9
commit f089df3a49
8 changed files with 532 additions and 13 deletions

92
examples/input.rs Normal file
View file

@ -0,0 +1,92 @@
use bevy::{
input::keyboard::{KeyboardInput, VirtualKeyCode},
prelude::*,
};
fn main() {
App::build()
.add_default_plugins()
.build_system(move_on_input_system)
.setup(setup)
.run();
}
pub fn move_on_input_system(resources: &mut Resources) -> Box<dyn Schedulable> {
let mut keyboard_input_event_reader = resources.get_event_reader::<KeyboardInput>();
let mut moving_left = false;
let mut moving_right = false;
SystemBuilder::new("input_handler")
.read_resource::<Time>()
.read_resource::<Events<KeyboardInput>>()
.with_query(<(Write<Translation>, Read<Handle<Mesh>>)>::query())
.build(
move |_command_buffer, world, (time, keyboard_input_events), mesh_query| {
for event in keyboard_input_events.iter(&mut keyboard_input_event_reader) {
match event {
KeyboardInput {
virtual_key_code: Some(VirtualKeyCode::Left),
state,
..
} => {
moving_left = state.is_pressed();
}
KeyboardInput {
virtual_key_code: Some(VirtualKeyCode::Right),
state,
..
} => {
moving_right = state.is_pressed();
}
_ => {}
}
}
for (mut translation, _mesh) in mesh_query.iter_mut(world) {
if moving_left {
translation.0 += math::vec3(1.0, 0.0, 0.0) * time.delta_seconds;
}
if moving_right {
translation.0 += math::vec3(-1.0, 0.0, 0.0) * time.delta_seconds;
}
}
},
)
}
fn setup(world: &mut World, resources: &mut Resources) {
let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let mut material_storage = resources
.get_mut::<AssetStorage<StandardMaterial>>()
.unwrap();
let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube));
let cube_material_handle = material_storage.add(StandardMaterial {
albedo: Color::rgb(0.5, 0.4, 0.3),
..Default::default()
});
world
.build()
// cube
.add_entity(MeshEntity {
mesh: cube_handle,
material: cube_material_handle,
translation: Translation::new(0.0, 0.0, 1.0),
..Default::default()
})
// light
.add_entity(LightEntity {
translation: Translation::new(4.0, -4.0, 5.0),
..Default::default()
})
// camera
.add_entity(CameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, 1.0),
)),
..Default::default()
})
.build();
}

View file

@ -7,7 +7,7 @@ use crate::{
legion::prelude::{Resources, Runnable, Schedulable, Schedule, Universe, World},
render::RenderPlugin,
ui::UiPlugin,
window::WindowPlugin,
window::WindowPlugin, input::InputPlugin,
};
use std::collections::HashMap;
@ -201,6 +201,7 @@ impl AppBuilder {
pub fn add_default_plugins(mut self) -> Self {
self = self
.add_plugin(CorePlugin::default())
.add_plugin(InputPlugin::default())
.add_plugin(WindowPlugin::default())
.add_plugin(RenderPlugin::default())
.add_plugin(UiPlugin::default());

View file

@ -4,6 +4,7 @@ use std::any::Any;
pub trait AppPlugin: Any + Send + Sync {
fn build(&self, app: AppBuilder) -> AppBuilder;
// TODO: consider removing "name" in favor of calling type_name::<Plugin>() from the host app
fn name(&self) -> &str;
}

218
src/input/keyboard.rs Normal file
View file

@ -0,0 +1,218 @@
#[derive(Debug, Clone)]
pub struct KeyboardInput {
pub scan_code: u32,
pub virtual_key_code: Option<VirtualKeyCode>,
pub state: KeyState,
}
#[derive(Debug, Clone)]
pub enum KeyState {
Pressed,
Released,
}
impl KeyState {
pub fn is_pressed(&self) -> bool {
match self {
KeyState::Pressed => true,
_ => false,
}
}
}
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum VirtualKeyCode {
/// The '1' key over the letters.
Key1,
/// The '2' key over the letters.
Key2,
/// The '3' key over the letters.
Key3,
/// The '4' key over the letters.
Key4,
/// The '5' key over the letters.
Key5,
/// The '6' key over the letters.
Key6,
/// The '7' key over the letters.
Key7,
/// The '8' key over the letters.
Key8,
/// The '9' key over the letters.
Key9,
/// The '0' key over the 'O' and 'P' keys.
Key0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
/// The Escape key, next to F1.
Escape,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
/// Print Screen/SysRq.
Snapshot,
/// Scroll Lock.
Scroll,
/// Pause/Break key, next to Scroll lock.
Pause,
/// `Insert`, next to Backspace.
Insert,
Home,
Delete,
End,
PageDown,
PageUp,
Left,
Up,
Right,
Down,
/// The Backspace key, right over Enter.
// TODO: rename
Back,
/// The Enter key.
Return,
/// The space bar.
Space,
/// The "Compose" key on Linux.
Compose,
Caret,
Numlock,
Numpad0,
Numpad1,
Numpad2,
Numpad3,
Numpad4,
Numpad5,
Numpad6,
Numpad7,
Numpad8,
Numpad9,
AbntC1,
AbntC2,
Add,
Apostrophe,
Apps,
At,
Ax,
Backslash,
Calculator,
Capital,
Colon,
Comma,
Convert,
Decimal,
Divide,
Equals,
Grave,
Kana,
Kanji,
LAlt,
LBracket,
LControl,
LShift,
LWin,
Mail,
MediaSelect,
MediaStop,
Minus,
Multiply,
Mute,
MyComputer,
NavigateForward, // also called "Prior"
NavigateBackward, // also called "Next"
NextTrack,
NoConvert,
NumpadComma,
NumpadEnter,
NumpadEquals,
OEM102,
Period,
PlayPause,
Power,
PrevTrack,
RAlt,
RBracket,
RControl,
RShift,
RWin,
Semicolon,
Slash,
Sleep,
Stop,
Subtract,
Sysrq,
Tab,
Underline,
Unlabeled,
VolumeDown,
VolumeUp,
Wake,
WebBack,
WebFavorites,
WebForward,
WebHome,
WebRefresh,
WebSearch,
WebStop,
Yen,
Copy,
Paste,
Cut,
}

17
src/input/mod.rs Normal file
View file

@ -0,0 +1,17 @@
pub mod keyboard;
use crate::{app::AppBuilder, prelude::AppPlugin};
use keyboard::KeyboardInput;
#[derive(Default)]
pub struct InputPlugin;
impl AppPlugin for InputPlugin {
fn build(&self, app: AppBuilder) -> AppBuilder {
app.add_event::<KeyboardInput>()
}
fn name(&self) -> &str {
"Input"
}
}

View file

@ -4,6 +4,7 @@ pub mod asset;
pub mod core;
pub mod diagnostic;
pub mod ecs;
pub mod input;
pub mod prelude;
pub mod render;
pub mod serialization;

View file

@ -0,0 +1,188 @@
use crate::input::keyboard::{KeyState, KeyboardInput, VirtualKeyCode};
impl From<&winit::event::KeyboardInput> for KeyboardInput {
fn from(keyboard_input: &winit::event::KeyboardInput) -> Self {
KeyboardInput {
scan_code: keyboard_input.scancode,
state: keyboard_input.state.into(),
virtual_key_code: keyboard_input.virtual_keycode.map(|v| v.into()),
}
}
}
impl From<winit::event::ElementState> for KeyState {
fn from(element_state: winit::event::ElementState) -> Self {
match element_state {
winit::event::ElementState::Pressed => KeyState::Pressed,
winit::event::ElementState::Released => KeyState::Released,
}
}
}
impl From<winit::event::VirtualKeyCode> for VirtualKeyCode {
fn from(virtual_key_code: winit::event::VirtualKeyCode) -> Self {
match virtual_key_code {
winit::event::VirtualKeyCode::Key1 => VirtualKeyCode::Key1,
winit::event::VirtualKeyCode::Key2 => VirtualKeyCode::Key2,
winit::event::VirtualKeyCode::Key3 => VirtualKeyCode::Key3,
winit::event::VirtualKeyCode::Key4 => VirtualKeyCode::Key4,
winit::event::VirtualKeyCode::Key5 => VirtualKeyCode::Key5,
winit::event::VirtualKeyCode::Key6 => VirtualKeyCode::Key6,
winit::event::VirtualKeyCode::Key7 => VirtualKeyCode::Key7,
winit::event::VirtualKeyCode::Key8 => VirtualKeyCode::Key8,
winit::event::VirtualKeyCode::Key9 => VirtualKeyCode::Key9,
winit::event::VirtualKeyCode::Key0 => VirtualKeyCode::Key0,
winit::event::VirtualKeyCode::A => VirtualKeyCode::A,
winit::event::VirtualKeyCode::B => VirtualKeyCode::B,
winit::event::VirtualKeyCode::C => VirtualKeyCode::C,
winit::event::VirtualKeyCode::D => VirtualKeyCode::D,
winit::event::VirtualKeyCode::E => VirtualKeyCode::E,
winit::event::VirtualKeyCode::F => VirtualKeyCode::F,
winit::event::VirtualKeyCode::G => VirtualKeyCode::G,
winit::event::VirtualKeyCode::H => VirtualKeyCode::H,
winit::event::VirtualKeyCode::I => VirtualKeyCode::I,
winit::event::VirtualKeyCode::J => VirtualKeyCode::J,
winit::event::VirtualKeyCode::K => VirtualKeyCode::K,
winit::event::VirtualKeyCode::L => VirtualKeyCode::L,
winit::event::VirtualKeyCode::M => VirtualKeyCode::M,
winit::event::VirtualKeyCode::N => VirtualKeyCode::N,
winit::event::VirtualKeyCode::O => VirtualKeyCode::O,
winit::event::VirtualKeyCode::P => VirtualKeyCode::P,
winit::event::VirtualKeyCode::Q => VirtualKeyCode::Q,
winit::event::VirtualKeyCode::R => VirtualKeyCode::R,
winit::event::VirtualKeyCode::S => VirtualKeyCode::S,
winit::event::VirtualKeyCode::T => VirtualKeyCode::T,
winit::event::VirtualKeyCode::U => VirtualKeyCode::U,
winit::event::VirtualKeyCode::V => VirtualKeyCode::V,
winit::event::VirtualKeyCode::W => VirtualKeyCode::W,
winit::event::VirtualKeyCode::X => VirtualKeyCode::X,
winit::event::VirtualKeyCode::Y => VirtualKeyCode::Y,
winit::event::VirtualKeyCode::Z => VirtualKeyCode::Z,
winit::event::VirtualKeyCode::Escape => VirtualKeyCode::Escape,
winit::event::VirtualKeyCode::F1 => VirtualKeyCode::F1,
winit::event::VirtualKeyCode::F2 => VirtualKeyCode::F2,
winit::event::VirtualKeyCode::F3 => VirtualKeyCode::F3,
winit::event::VirtualKeyCode::F4 => VirtualKeyCode::F4,
winit::event::VirtualKeyCode::F5 => VirtualKeyCode::F5,
winit::event::VirtualKeyCode::F6 => VirtualKeyCode::F6,
winit::event::VirtualKeyCode::F7 => VirtualKeyCode::F7,
winit::event::VirtualKeyCode::F8 => VirtualKeyCode::F8,
winit::event::VirtualKeyCode::F9 => VirtualKeyCode::F9,
winit::event::VirtualKeyCode::F10 => VirtualKeyCode::F10,
winit::event::VirtualKeyCode::F11 => VirtualKeyCode::F11,
winit::event::VirtualKeyCode::F12 => VirtualKeyCode::F12,
winit::event::VirtualKeyCode::F13 => VirtualKeyCode::F13,
winit::event::VirtualKeyCode::F14 => VirtualKeyCode::F14,
winit::event::VirtualKeyCode::F15 => VirtualKeyCode::F15,
winit::event::VirtualKeyCode::F16 => VirtualKeyCode::F16,
winit::event::VirtualKeyCode::F17 => VirtualKeyCode::F17,
winit::event::VirtualKeyCode::F18 => VirtualKeyCode::F18,
winit::event::VirtualKeyCode::F19 => VirtualKeyCode::F19,
winit::event::VirtualKeyCode::F20 => VirtualKeyCode::F20,
winit::event::VirtualKeyCode::F21 => VirtualKeyCode::F21,
winit::event::VirtualKeyCode::F22 => VirtualKeyCode::F22,
winit::event::VirtualKeyCode::F23 => VirtualKeyCode::F23,
winit::event::VirtualKeyCode::F24 => VirtualKeyCode::F24,
winit::event::VirtualKeyCode::Snapshot => VirtualKeyCode::Snapshot,
winit::event::VirtualKeyCode::Scroll => VirtualKeyCode::Scroll,
winit::event::VirtualKeyCode::Pause => VirtualKeyCode::Pause,
winit::event::VirtualKeyCode::Insert => VirtualKeyCode::Insert,
winit::event::VirtualKeyCode::Home => VirtualKeyCode::Home,
winit::event::VirtualKeyCode::Delete => VirtualKeyCode::Delete,
winit::event::VirtualKeyCode::End => VirtualKeyCode::End,
winit::event::VirtualKeyCode::PageDown => VirtualKeyCode::PageDown,
winit::event::VirtualKeyCode::PageUp => VirtualKeyCode::PageUp,
winit::event::VirtualKeyCode::Left => VirtualKeyCode::Left,
winit::event::VirtualKeyCode::Up => VirtualKeyCode::Up,
winit::event::VirtualKeyCode::Right => VirtualKeyCode::Right,
winit::event::VirtualKeyCode::Down => VirtualKeyCode::Down,
winit::event::VirtualKeyCode::Back => VirtualKeyCode::Back,
winit::event::VirtualKeyCode::Return => VirtualKeyCode::Return,
winit::event::VirtualKeyCode::Space => VirtualKeyCode::Space,
winit::event::VirtualKeyCode::Compose => VirtualKeyCode::Compose,
winit::event::VirtualKeyCode::Caret => VirtualKeyCode::Caret,
winit::event::VirtualKeyCode::Numlock => VirtualKeyCode::Numlock,
winit::event::VirtualKeyCode::Numpad0 => VirtualKeyCode::Numpad0,
winit::event::VirtualKeyCode::Numpad1 => VirtualKeyCode::Numpad1,
winit::event::VirtualKeyCode::Numpad2 => VirtualKeyCode::Numpad2,
winit::event::VirtualKeyCode::Numpad3 => VirtualKeyCode::Numpad3,
winit::event::VirtualKeyCode::Numpad4 => VirtualKeyCode::Numpad4,
winit::event::VirtualKeyCode::Numpad5 => VirtualKeyCode::Numpad5,
winit::event::VirtualKeyCode::Numpad6 => VirtualKeyCode::Numpad6,
winit::event::VirtualKeyCode::Numpad7 => VirtualKeyCode::Numpad7,
winit::event::VirtualKeyCode::Numpad8 => VirtualKeyCode::Numpad8,
winit::event::VirtualKeyCode::Numpad9 => VirtualKeyCode::Numpad9,
winit::event::VirtualKeyCode::AbntC1 => VirtualKeyCode::AbntC1,
winit::event::VirtualKeyCode::AbntC2 => VirtualKeyCode::AbntC2,
winit::event::VirtualKeyCode::Add => VirtualKeyCode::Add,
winit::event::VirtualKeyCode::Apostrophe => VirtualKeyCode::Apostrophe,
winit::event::VirtualKeyCode::Apps => VirtualKeyCode::Apps,
winit::event::VirtualKeyCode::At => VirtualKeyCode::At,
winit::event::VirtualKeyCode::Ax => VirtualKeyCode::Ax,
winit::event::VirtualKeyCode::Backslash => VirtualKeyCode::Backslash,
winit::event::VirtualKeyCode::Calculator => VirtualKeyCode::Calculator,
winit::event::VirtualKeyCode::Capital => VirtualKeyCode::Capital,
winit::event::VirtualKeyCode::Colon => VirtualKeyCode::Colon,
winit::event::VirtualKeyCode::Comma => VirtualKeyCode::Comma,
winit::event::VirtualKeyCode::Convert => VirtualKeyCode::Convert,
winit::event::VirtualKeyCode::Decimal => VirtualKeyCode::Decimal,
winit::event::VirtualKeyCode::Divide => VirtualKeyCode::Divide,
winit::event::VirtualKeyCode::Equals => VirtualKeyCode::Equals,
winit::event::VirtualKeyCode::Grave => VirtualKeyCode::Grave,
winit::event::VirtualKeyCode::Kana => VirtualKeyCode::Kana,
winit::event::VirtualKeyCode::Kanji => VirtualKeyCode::Kanji,
winit::event::VirtualKeyCode::LAlt => VirtualKeyCode::LAlt,
winit::event::VirtualKeyCode::LBracket => VirtualKeyCode::LBracket,
winit::event::VirtualKeyCode::LControl => VirtualKeyCode::LControl,
winit::event::VirtualKeyCode::LShift => VirtualKeyCode::LShift,
winit::event::VirtualKeyCode::LWin => VirtualKeyCode::LWin,
winit::event::VirtualKeyCode::Mail => VirtualKeyCode::Mail,
winit::event::VirtualKeyCode::MediaSelect => VirtualKeyCode::MediaSelect,
winit::event::VirtualKeyCode::MediaStop => VirtualKeyCode::MediaStop,
winit::event::VirtualKeyCode::Minus => VirtualKeyCode::Minus,
winit::event::VirtualKeyCode::Multiply => VirtualKeyCode::Multiply,
winit::event::VirtualKeyCode::Mute => VirtualKeyCode::Mute,
winit::event::VirtualKeyCode::MyComputer => VirtualKeyCode::MyComputer,
winit::event::VirtualKeyCode::NavigateForward => VirtualKeyCode::NavigateForward,
winit::event::VirtualKeyCode::NavigateBackward => VirtualKeyCode::NavigateBackward,
winit::event::VirtualKeyCode::NextTrack => VirtualKeyCode::NextTrack,
winit::event::VirtualKeyCode::NoConvert => VirtualKeyCode::NoConvert,
winit::event::VirtualKeyCode::NumpadComma => VirtualKeyCode::NumpadComma,
winit::event::VirtualKeyCode::NumpadEnter => VirtualKeyCode::NumpadEnter,
winit::event::VirtualKeyCode::NumpadEquals => VirtualKeyCode::NumpadEquals,
winit::event::VirtualKeyCode::OEM102 => VirtualKeyCode::OEM102,
winit::event::VirtualKeyCode::Period => VirtualKeyCode::Period,
winit::event::VirtualKeyCode::PlayPause => VirtualKeyCode::PlayPause,
winit::event::VirtualKeyCode::Power => VirtualKeyCode::Power,
winit::event::VirtualKeyCode::PrevTrack => VirtualKeyCode::PrevTrack,
winit::event::VirtualKeyCode::RAlt => VirtualKeyCode::RAlt,
winit::event::VirtualKeyCode::RBracket => VirtualKeyCode::RBracket,
winit::event::VirtualKeyCode::RControl => VirtualKeyCode::RControl,
winit::event::VirtualKeyCode::RShift => VirtualKeyCode::RShift,
winit::event::VirtualKeyCode::RWin => VirtualKeyCode::RWin,
winit::event::VirtualKeyCode::Semicolon => VirtualKeyCode::Semicolon,
winit::event::VirtualKeyCode::Slash => VirtualKeyCode::Slash,
winit::event::VirtualKeyCode::Sleep => VirtualKeyCode::Sleep,
winit::event::VirtualKeyCode::Stop => VirtualKeyCode::Stop,
winit::event::VirtualKeyCode::Subtract => VirtualKeyCode::Subtract,
winit::event::VirtualKeyCode::Sysrq => VirtualKeyCode::Sysrq,
winit::event::VirtualKeyCode::Tab => VirtualKeyCode::Tab,
winit::event::VirtualKeyCode::Underline => VirtualKeyCode::Underline,
winit::event::VirtualKeyCode::Unlabeled => VirtualKeyCode::Unlabeled,
winit::event::VirtualKeyCode::VolumeDown => VirtualKeyCode::VolumeDown,
winit::event::VirtualKeyCode::VolumeUp => VirtualKeyCode::VolumeUp,
winit::event::VirtualKeyCode::Wake => VirtualKeyCode::Wake,
winit::event::VirtualKeyCode::WebBack => VirtualKeyCode::WebBack,
winit::event::VirtualKeyCode::WebFavorites => VirtualKeyCode::WebFavorites,
winit::event::VirtualKeyCode::WebForward => VirtualKeyCode::WebForward,
winit::event::VirtualKeyCode::WebHome => VirtualKeyCode::WebHome,
winit::event::VirtualKeyCode::WebRefresh => VirtualKeyCode::WebRefresh,
winit::event::VirtualKeyCode::WebSearch => VirtualKeyCode::WebSearch,
winit::event::VirtualKeyCode::WebStop => VirtualKeyCode::WebStop,
winit::event::VirtualKeyCode::Yen => VirtualKeyCode::Yen,
winit::event::VirtualKeyCode::Copy => VirtualKeyCode::Copy,
winit::event::VirtualKeyCode::Paste => VirtualKeyCode::Paste,
winit::event::VirtualKeyCode::Cut => VirtualKeyCode::Cut,
}
}
}

View file

@ -1,7 +1,8 @@
mod converters;
mod winit_windows;
pub use winit_windows::*;
use crate::prelude::*;
use crate::{input::keyboard::KeyboardInput, prelude::*};
use super::{CreateWindow, Window, WindowCreated, WindowResized, Windows};
use winit::{
@ -15,7 +16,11 @@ pub struct WinitPlugin;
impl AppPlugin for WinitPlugin {
fn build(&self, app: AppBuilder) -> AppBuilder {
app.add_resource(WinitWindows::default())
app
// TODO: It would be great to provide a raw winit WindowEvent here, but the lifetime on it is
// stopping us. there are plans to remove the lifetime: https://github.com/rust-windowing/winit/pull/1456
// .add_event::<winit::event::WindowEvent>()
.add_resource(WinitWindows::default())
.set_runner(winit_runner)
}
@ -68,18 +73,14 @@ pub fn winit_runner(mut app: App) {
});
}
event::Event::WindowEvent { event, .. } => match event {
WindowEvent::KeyboardInput {
input:
event::KeyboardInput {
virtual_keycode: Some(event::VirtualKeyCode::Escape),
state: event::ElementState::Pressed,
..
},
..
}
| WindowEvent::CloseRequested => {
WindowEvent::CloseRequested => {
*control_flow = ControlFlow::Exit;
}
WindowEvent::KeyboardInput { ref input, .. } => {
let mut keyboard_input_events =
app.resources.get_mut::<Events<KeyboardInput>>().unwrap();
keyboard_input_events.send(input.into());
}
_ => {}
},
event::Event::MainEventsCleared => {