bracket_terminal/input/
input_handler.rs

1use super::BEvent;
2use crate::prelude::{BTerm, VirtualKeyCode};
3use bracket_geometry::prelude::Point;
4use std::collections::{HashSet, VecDeque};
5
6/// Internal: clears the current frame's input state. Used by HAL backends to indicate the start of a new frame
7/// for input.
8pub(crate) fn clear_input_state(term: &mut BTerm) {
9    term.key = None;
10    term.left_click = false;
11    term.web_button = None;
12}
13
14/// Represents the current input state. The old key/mouse fields remain available for compatibility.
15#[derive(Clone, Debug)]
16pub struct Input {
17    keys_down: HashSet<VirtualKeyCode>,
18    scancodes: HashSet<u32>,
19    mouse_buttons: HashSet<usize>,
20    mouse_pixel: (f64, f64),
21    mouse_tile: Vec<(i32, i32)>,
22    pub(crate) use_events: bool,
23    event_queue: VecDeque<BEvent>,
24    scale_factor: f64,
25}
26
27impl Input {
28    /// Internal - instantiates a new Input object.
29    pub(crate) fn new() -> Self {
30        Self {
31            keys_down: HashSet::new(),
32            scancodes: HashSet::new(),
33            mouse_buttons: HashSet::new(),
34            mouse_pixel: (0.0, 0.0),
35            mouse_tile: Vec::new(),
36            event_queue: VecDeque::new(),
37            use_events: false, // Not enabled by default so that systems not using it don't fill up RAM for no reason
38            scale_factor: 1.0,
39        }
40    }
41
42    /// Checks to see if a key is pressed. True if it is, false otherwise.
43    pub fn is_key_pressed(&self, key: VirtualKeyCode) -> bool {
44        self.keys_down.contains(&key)
45    }
46
47    /// Checks to see if a key is pressed by scancode. True if it is, false if it isn't.
48    pub fn is_scancode_pressed(&self, scan_code: u32) -> bool {
49        self.scancodes.contains(&scan_code)
50    }
51
52    /// Checks to see if a mouse button is pressed. 0 = left, 1 = right, 2 = middle, etc. is the convention for
53    /// button numbering.
54    pub fn is_mouse_button_pressed(&self, button_num: usize) -> bool {
55        self.mouse_buttons.contains(&button_num)
56    }
57
58    /// HashSet of pressed mouse buttons
59    pub fn mouse_button_pressed_set(&self) -> &HashSet<usize> {
60        &self.mouse_buttons
61    }
62
63    /// HashSet of pressed keyboard scan codes
64    pub fn scan_code_pressed_set(&self) -> &HashSet<u32> {
65        &self.scancodes
66    }
67
68    /// HashSet of pressed keyboard scan codes
69    pub fn key_pressed_set(&self) -> &HashSet<VirtualKeyCode> {
70        &self.keys_down
71    }
72
73    /// Returns the current mouse position (0,0 if there isn't one yet), in TILE coordinates for the specified
74    /// console layer.
75    pub fn mouse_tile_pos(&self, console: usize) -> (i32, i32) {
76        if console < self.mouse_tile.len() {
77            self.mouse_tile[console]
78        } else {
79            (0, 0)
80        }
81    }
82
83    /// Returns the current mouse position (0,0 if there isn't one yet), in TILE coordinates for the specified
84    /// console layer in Point format.
85    pub fn mouse_tile(&self, console: usize) -> Point {
86        if console < self.mouse_tile.len() {
87            Point::from_tuple(self.mouse_tile[console])
88        } else {
89            Point::zero()
90        }
91    }
92
93    /// Return the current mouse position in pixels.
94    pub fn mouse_pixel_pos(&self) -> (f64, f64) {
95        (self.mouse_pixel.0, self.mouse_pixel.1)
96    }
97
98    /// Call this to enable the event queue. Otherwise, events will not be tracked/stored outside of the
99    /// HAL setup (to avoid continually filling a buffer that isn't being used).
100    pub fn activate_event_queue(&mut self) {
101        self.use_events = true;
102    }
103
104    /// Pop a single event from the event queue. Returns None if there aren't any events.
105    pub fn pop(&mut self) -> Option<BEvent> {
106        self.event_queue.pop_back()
107    }
108
109    /// Provides a for_each function for all messages in the queue.
110    pub fn for_each_message<F>(&mut self, mut action: F)
111    where
112        F: FnMut(BEvent),
113    {
114        loop {
115            let e = self.event_queue.pop_back();
116            if let Some(e) = e {
117                action(e);
118            } else {
119                break;
120            }
121        }
122    }
123
124    /// Gets the current scale factor
125    pub fn get_scale_factor(&self) -> f64 {
126        self.scale_factor
127    }
128
129    /// Internal - do not use
130    #[allow(dead_code)]
131    pub(crate) fn set_scale_factor(&mut self, scale: f64) {
132        self.scale_factor = scale;
133    }
134
135    /// Internal - do not use
136    pub(crate) fn on_key_down(&mut self, key: VirtualKeyCode, scan_code: u32) {
137        self.keys_down.insert(key);
138        self.scancodes.insert(scan_code);
139    }
140
141    /// Internal - do not use
142    pub(crate) fn on_key_up(&mut self, key: VirtualKeyCode, scan_code: u32) {
143        self.keys_down.remove(&key);
144        self.scancodes.remove(&scan_code);
145    }
146
147    /// Internal - do not use
148    pub(crate) fn on_mouse_button_down(&mut self, button_num: usize) {
149        self.mouse_buttons.insert(button_num);
150        self.push_event(BEvent::MouseButtonDown { button: button_num });
151    }
152
153    /// Internal - do not use
154    pub(crate) fn on_mouse_button_up(&mut self, button_num: usize) {
155        self.mouse_buttons.remove(&button_num);
156        self.push_event(BEvent::MouseButtonUp { button: button_num });
157    }
158
159    /// Internal - do not use
160    pub(crate) fn on_mouse_pixel_position(&mut self, x: f64, y: f64) {
161        self.mouse_pixel = (x, y);
162        self.push_event(BEvent::CursorMoved {
163            position: Point::new(x as i32, y as i32),
164        });
165    }
166
167    /// Internal - do not use
168    pub(crate) fn on_mouse_tile_position(&mut self, console: usize, x: i32, y: i32) {
169        while self.mouse_tile.len() < console + 1 {
170            self.mouse_tile.push((0, 0));
171        }
172        self.mouse_tile[console] = (x, y);
173    }
174
175    /// Internal - do not use
176    pub(crate) fn push_event(&mut self, event: BEvent) {
177        if self.use_events {
178            self.event_queue.push_front(event);
179        }
180    }
181}