aboutsummaryrefslogtreecommitdiff
path: root/src/input
diff options
context:
space:
mode:
authorLibravatar Silas Bartha <silas@exvacuum.dev>2024-06-04 15:00:16 -0400
committerLibravatar Silas Bartha <silas@exvacuum.dev>2024-06-04 15:00:16 -0400
commita002e4d738535e6ca779c71231f7b84864b9a8d0 (patch)
tree8ec521b535f3820328f9ea6f2511ca29c630b82f /src/input
parent56aafda8495243fa939bdce01f36d4adbf4ec556 (diff)
Refactored + Renamed + Added Docs
Diffstat (limited to 'src/input')
-rw-r--r--src/input/events.rs6
-rw-r--r--src/input/mod.rs8
-rw-r--r--src/input/resources.rs48
-rw-r--r--src/input/systems.rs46
4 files changed, 108 insertions, 0 deletions
diff --git a/src/input/events.rs b/src/input/events.rs
new file mode 100644
index 0000000..cf46445
--- /dev/null
+++ b/src/input/events.rs
@@ -0,0 +1,6 @@
+use bevy::prelude::*;
+use crossterm::event::Event;
+
+/// An event triggered when a crossterm input event is received
+#[derive(Event)]
+pub struct TerminalInputEvent(pub Event);
diff --git a/src/input/mod.rs b/src/input/mod.rs
new file mode 100644
index 0000000..80c36bc
--- /dev/null
+++ b/src/input/mod.rs
@@ -0,0 +1,8 @@
+/// Events for this module
+pub mod events;
+
+/// Resources for this module
+pub mod resources;
+
+/// Systems for this module
+pub(crate) mod systems;
diff --git a/src/input/resources.rs b/src/input/resources.rs
new file mode 100644
index 0000000..afe6353
--- /dev/null
+++ b/src/input/resources.rs
@@ -0,0 +1,48 @@
+use bevy::{prelude::*, utils::HashSet};
+use crossterm::event::{Event, KeyCode};
+use std::sync::{Arc, Mutex};
+
+/// Resource containing currently pressed and released keys
+#[derive(Resource, Default)]
+pub struct TerminalInput {
+ pressed_keys: HashSet<KeyCode>,
+ released_keys: HashSet<KeyCode>,
+}
+
+impl TerminalInput {
+ /// Gets whether the given key is pressed
+ pub fn is_pressed(&self, code: KeyCode) -> bool {
+ self.pressed_keys.contains(&code)
+ }
+
+ /// Gets whether the given key is released
+ pub fn is_released(&self, code: KeyCode) -> bool {
+ self.released_keys.contains(&code)
+ }
+
+ /// Sets given key to pressed
+ pub(super) fn press(&mut self, code: KeyCode) {
+ if !self.is_pressed(code) {
+ self.pressed_keys.insert(code);
+ }
+ }
+
+ /// Sets given key to released and removes pressed state
+ pub(super) fn release(&mut self, code: KeyCode) {
+ if self.is_pressed(code) {
+ self.pressed_keys.remove(&code);
+ }
+ if !self.is_released(code) {
+ self.released_keys.insert(code);
+ }
+ }
+
+ /// Clears all released keys
+ pub(super) fn clear_released(&mut self) {
+ self.released_keys.clear();
+ }
+}
+
+/// Event queue for crossterm input event thread
+#[derive(Resource, Default)]
+pub(crate) struct EventQueue(pub(super) Arc<Mutex<Vec<Event>>>);
diff --git a/src/input/systems.rs b/src/input/systems.rs
new file mode 100644
index 0000000..3b7f11d
--- /dev/null
+++ b/src/input/systems.rs
@@ -0,0 +1,46 @@
+use bevy::prelude::*;
+use crossterm::event::{read, Event, KeyEventKind};
+
+use super::{events::TerminalInputEvent, resources::{EventQueue, TerminalInput}};
+
+/// Initializes event queue and thread
+pub fn setup_input(event_queue: Res<EventQueue>) {
+ let event_queue = event_queue.0.clone();
+ std::thread::spawn(move || {
+ loop {
+ // `read()` blocks until an `Event` is available
+ match read() {
+ Ok(event) => {
+ event_queue.lock().unwrap().push(event);
+ }
+ Err(err) => {
+ panic!("Error reading input events: {:?}", err);
+ }
+ }
+ }
+ });
+}
+
+/// Reads events from queue and broadcasts corresponding `TerminalInputEvent`s
+pub fn input_handling(
+ event_queue: Res<EventQueue>,
+ mut input: ResMut<TerminalInput>,
+ mut event_writer: EventWriter<TerminalInputEvent>,
+) {
+ input.clear_released();
+ let mut event_queue = event_queue.0.lock().unwrap();
+ while let Some(event) = event_queue.pop() {
+ if let Event::Key(event) = event {
+ match event.kind {
+ KeyEventKind::Press => {
+ input.press(event.code);
+ }
+ KeyEventKind::Release => {
+ input.release(event.code);
+ }
+ _ => (),
+ }
+ }
+ event_writer.send(TerminalInputEvent(event));
+ }
+}