input: make new Input resource generic and add Input<MouseButton>

This commit is contained in:
Carter Anderson 2020-06-04 23:34:21 -07:00
parent fcecf78609
commit 5b6f24d6a2
8 changed files with 140 additions and 77 deletions

View File

@ -1,72 +1,52 @@
use crate::keyboard::{KeyCode, KeyboardInput, ElementState}; use std::{collections::HashSet, hash::Hash};
use bevy_app::{EventReader, Events};
use legion::prelude::{Res, ResMut};
use std::collections::HashSet;
#[derive(Default)] pub struct Input<T> {
pub struct Input { pressed: HashSet<T>,
pressed_keys: HashSet<KeyCode>, just_pressed: HashSet<T>,
just_pressed_keys: HashSet<KeyCode>, just_released: HashSet<T>,
just_released_keys: HashSet<KeyCode>,
} }
impl Input { impl<T> Default for Input<T> {
pub fn press_key(&mut self, key_code: KeyCode) { fn default() -> Self {
if !self.key_pressed(key_code) { Self {
self.just_pressed_keys.insert(key_code); pressed: Default::default(),
just_pressed: Default::default(),
just_released: Default::default(),
}
}
} }
self.pressed_keys.insert(key_code); impl<T> Input<T>
where
T: Copy + Eq + Hash,
{
pub fn press(&mut self, input: T) {
if !self.pressed(input) {
self.just_pressed.insert(input);
} }
pub fn release_key(&mut self, key_code: KeyCode) { self.pressed.insert(input);
self.pressed_keys.remove(&key_code);
self.just_released_keys.insert(key_code);
} }
pub fn key_pressed(&self, key_code: KeyCode) -> bool { pub fn pressed(&self, input: T) -> bool {
self.pressed_keys.contains(&key_code) self.pressed.contains(&input)
} }
pub fn key_just_pressed(&self, key_code: KeyCode) -> bool { pub fn release(&mut self, input: T) {
self.just_pressed_keys.contains(&key_code) self.pressed.remove(&input);
self.just_released.insert(input);
} }
pub fn key_just_released(&self, key_code: KeyCode) -> bool { pub fn just_pressed(&self, input: T) -> bool {
self.just_released_keys.contains(&key_code) self.just_pressed.contains(&input)
}
pub fn just_released(&self, input: T) -> bool {
self.just_released.contains(&input)
} }
pub fn update(&mut self) { pub fn update(&mut self) {
self.just_pressed_keys.clear(); self.just_pressed.clear();
self.just_released_keys.clear(); self.just_released.clear();
}
}
#[derive(Default)]
pub struct InputState {
keyboard_input_event_reader: EventReader<KeyboardInput>,
}
pub fn input_system(
mut state: ResMut<InputState>,
mut input: ResMut<Input>,
keyboard_input_events: Res<Events<KeyboardInput>>,
) {
input.update();
for event in state
.keyboard_input_event_reader
.iter(&keyboard_input_events)
{
if let KeyboardInput {
key_code: Some(key_code),
state,
..
} = event
{
match state {
ElementState::Pressed => input.press_key(*key_code),
ElementState::Released => input.release_key(*key_code),
}
}
} }
} }

View File

@ -1,3 +1,7 @@
use bevy_app::{Events, EventReader};
use legion::prelude::{Res, ResMut};
use crate::Input;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct KeyboardInput { pub struct KeyboardInput {
pub scan_code: u32, pub scan_code: u32,
@ -20,6 +24,35 @@ impl ElementState {
} }
} }
#[derive(Default)]
pub struct KeyboardInputState {
keyboard_input_event_reader: EventReader<KeyboardInput>,
}
pub fn keyboard_input_system(
mut state: ResMut<KeyboardInputState>,
mut keyboard_input: ResMut<Input<KeyCode>>,
keyboard_input_events: Res<Events<KeyboardInput>>,
) {
keyboard_input.update();
for event in state
.keyboard_input_event_reader
.iter(&keyboard_input_events)
{
if let KeyboardInput {
key_code: Some(key_code),
state,
..
} = event
{
match state {
ElementState::Pressed => keyboard_input.press(*key_code),
ElementState::Released => keyboard_input.release(*key_code),
}
}
}
}
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)] #[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
#[repr(u32)] #[repr(u32)]
pub enum KeyCode { pub enum KeyCode {

View File

@ -6,9 +6,12 @@ pub mod system;
pub use input::*; pub use input::*;
use bevy_app::{AppBuilder, AppPlugin}; use bevy_app::{AppBuilder, AppPlugin};
use keyboard::KeyboardInput; use keyboard::{keyboard_input_system, KeyCode, KeyboardInput, KeyboardInputState};
use mouse::{MouseButtonInput, MouseMotionInput};
use legion::prelude::IntoSystem; use legion::prelude::IntoSystem;
use mouse::{
mouse_button_input_system, MouseButton, MouseButtonInput, MouseButtonInputState,
MouseMotion,
};
#[derive(Default)] #[derive(Default)]
pub struct InputPlugin; pub struct InputPlugin;
@ -17,9 +20,18 @@ impl AppPlugin for InputPlugin {
fn build(&self, app: &mut AppBuilder) { fn build(&self, app: &mut AppBuilder) {
app.add_event::<KeyboardInput>() app.add_event::<KeyboardInput>()
.add_event::<MouseButtonInput>() .add_event::<MouseButtonInput>()
.add_event::<MouseMotionInput>() .add_event::<MouseMotion>()
.init_resource::<Input>() .init_resource::<Input<KeyCode>>()
.init_resource::<InputState>() .init_resource::<KeyboardInputState>()
.add_system_to_stage(bevy_app::stage::EVENT_UPDATE, input_system.system()); .add_system_to_stage(
bevy_app::stage::EVENT_UPDATE,
keyboard_input_system.system(),
)
.init_resource::<Input<MouseButton>>()
.init_resource::<MouseButtonInputState>()
.add_system_to_stage(
bevy_app::stage::EVENT_UPDATE,
mouse_button_input_system.system(),
);
} }
} }

View File

@ -1,5 +1,8 @@
use super::keyboard::ElementState; use super::keyboard::ElementState;
use crate::Input;
use bevy_app::{EventReader, Events};
use glam::Vec2; use glam::Vec2;
use legion::prelude::{Res, ResMut};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MouseButtonInput { pub struct MouseButtonInput {
@ -16,6 +19,28 @@ pub enum MouseButton {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MouseMotionInput { pub struct MouseMotion {
pub delta: Vec2, pub delta: Vec2,
} }
#[derive(Default)]
pub struct MouseButtonInputState {
mouse_button_input_event_reader: EventReader<MouseButtonInput>,
}
pub fn mouse_button_input_system(
mut state: ResMut<MouseButtonInputState>,
mut mouse_button_input: ResMut<Input<MouseButton>>,
mouse_button_input_events: Res<Events<MouseButtonInput>>,
) {
mouse_button_input.update();
for event in state
.mouse_button_input_event_reader
.iter(&mouse_button_input_events)
{
match event.state {
ElementState::Pressed => mouse_button_input.press(event.button),
ElementState::Released => mouse_button_input.release(event.button),
}
}
}

View File

@ -4,7 +4,7 @@ pub use winit_windows::*;
use bevy_input::{ use bevy_input::{
keyboard::KeyboardInput, keyboard::KeyboardInput,
mouse::{MouseButtonInput, MouseMotionInput}, mouse::{MouseButtonInput, MouseMotion},
}; };
use bevy_app::{App, AppBuilder, AppExit, AppPlugin, EventReader, Events}; use bevy_app::{App, AppBuilder, AppExit, AppPlugin, EventReader, Events};
@ -125,8 +125,8 @@ pub fn winit_runner(mut app: App) {
event::Event::DeviceEvent { ref event, .. } => match event { event::Event::DeviceEvent { ref event, .. } => match event {
DeviceEvent::MouseMotion { delta } => { DeviceEvent::MouseMotion { delta } => {
let mut mouse_motion_events = let mut mouse_motion_events =
app.resources.get_mut::<Events<MouseMotionInput>>().unwrap(); app.resources.get_mut::<Events<MouseMotion>>().unwrap();
mouse_motion_events.send(MouseMotionInput { mouse_motion_events.send(MouseMotion {
delta: Vec2::new(delta.0 as f32, delta.1 as f32), delta: Vec2::new(delta.0 as f32, delta.1 as f32),
}); });
} }

View File

@ -13,17 +13,17 @@ fn main() {
fn move_on_input( fn move_on_input(
world: &mut SubWorld, world: &mut SubWorld,
time: Res<Time>, time: Res<Time>,
input: Res<Input>, keyboard_input: Res<Input<KeyCode>>,
query: &mut Query<(Write<Translation>, Read<Handle<Mesh>>)>, query: &mut Query<(Write<Translation>, Read<Handle<Mesh>>)>,
) { ) {
let moving_left = input.key_pressed(KeyCode::Left); let moving_left = keyboard_input.pressed(KeyCode::Left);
let moving_right = input.key_pressed(KeyCode::Right); let moving_right = keyboard_input.pressed(KeyCode::Right);
if input.key_just_pressed(KeyCode::Left) { if keyboard_input.just_pressed(KeyCode::Left) {
println!("left just pressed"); println!("left just pressed");
} }
if input.key_just_released(KeyCode::Left) { if keyboard_input.just_released(KeyCode::Left) {
println!("left just released"); println!("left just released");
} }

View File

@ -1,29 +1,40 @@
use bevy::{ use bevy::{
input::mouse::{MouseButtonInput, MouseMotionInput}, input::mouse::{MouseButtonInput, MouseMotion},
prelude::*, prelude::*,
window::CursorMoved,
}; };
use bevy_window::CursorMoved;
fn main() { fn main() {
App::build() App::build()
.add_default_plugins() .add_default_plugins()
.init_resource::<State>() .init_resource::<State>()
.add_system(mouse_input_system.system()) .add_system(mouse_click_system.system())
.add_system(mouse_input_event_system.system())
.run(); .run();
} }
fn mouse_click_system(mouse_button_input: Res<Input<MouseButton>>) {
if mouse_button_input.just_pressed(MouseButton::Left) {
println!("left mouse clicked");
}
if mouse_button_input.just_released(MouseButton::Left) {
println!("left mouse released");
}
}
#[derive(Default)] #[derive(Default)]
struct State { struct State {
mouse_button_event_reader: EventReader<MouseButtonInput>, mouse_button_event_reader: EventReader<MouseButtonInput>,
mouse_motion_event_reader: EventReader<MouseMotionInput>, mouse_motion_event_reader: EventReader<MouseMotion>,
cursor_moved_event_reader: EventReader<CursorMoved>, cursor_moved_event_reader: EventReader<CursorMoved>,
} }
/// prints out mouse events as they come in /// prints out all mouse events as they come in
fn mouse_input_system( fn mouse_input_event_system(
mut state: ResMut<State>, mut state: ResMut<State>,
mouse_button_input_events: Res<Events<MouseButtonInput>>, mouse_button_input_events: Res<Events<MouseButtonInput>>,
mouse_motion_events: Res<Events<MouseMotionInput>>, mouse_motion_events: Res<Events<MouseMotion>>,
cursor_moved_events: Res<Events<CursorMoved>>, cursor_moved_events: Res<Events<CursorMoved>>,
) { ) {
for event in state for event in state

View File

@ -9,6 +9,8 @@ pub use crate::core::{
pub use crate::derive::*; pub use crate::derive::*;
#[cfg(feature = "diagnostic")] #[cfg(feature = "diagnostic")]
pub use crate::diagnostic::DiagnosticsPlugin; pub use crate::diagnostic::DiagnosticsPlugin;
#[cfg(feature = "input")]
pub use crate::input::{Input, mouse::MouseButton, keyboard::KeyCode};
#[cfg(feature = "pbr")] #[cfg(feature = "pbr")]
pub use crate::pbr::{entity::*, light::Light, material::StandardMaterial}; pub use crate::pbr::{entity::*, light::Light, material::StandardMaterial};
#[cfg(feature = "property")] #[cfg(feature = "property")]