1use std::collections::HashSet;
4
5use crate::prelude::screen_height;
6use crate::prelude::screen_width;
7use crate::Vec2;
8use crate::{get_context, DroppedFile};
9pub use miniquad::{KeyCode, MouseButton};
10
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12pub enum TouchPhase {
13 Started,
14 Stationary,
15 Moved,
16 Ended,
17 Cancelled,
18}
19
20impl From<miniquad::TouchPhase> for TouchPhase {
21 fn from(miniquad_phase: miniquad::TouchPhase) -> TouchPhase {
22 match miniquad_phase {
23 miniquad::TouchPhase::Started => TouchPhase::Started,
24 miniquad::TouchPhase::Moved => TouchPhase::Moved,
25 miniquad::TouchPhase::Ended => TouchPhase::Ended,
26 miniquad::TouchPhase::Cancelled => TouchPhase::Cancelled,
27 }
28 }
29}
30
31#[derive(Clone, Debug)]
32pub struct Touch {
33 pub id: u64,
34 pub phase: TouchPhase,
35 pub position: Vec2,
36}
37
38pub fn set_cursor_grab(grab: bool) {
40 let context = get_context();
41 context.cursor_grabbed = grab;
42 miniquad::window::set_cursor_grab(grab);
43}
44
45pub fn show_mouse(shown: bool) {
47 miniquad::window::show_mouse(shown);
48}
49
50pub fn mouse_position() -> (f32, f32) {
52 let context = get_context();
53
54 (
55 context.mouse_position.x / miniquad::window::dpi_scale(),
56 context.mouse_position.y / miniquad::window::dpi_scale(),
57 )
58}
59
60pub fn mouse_position_local() -> Vec2 {
62 let (pixels_x, pixels_y) = mouse_position();
63
64 convert_to_local(Vec2::new(pixels_x, pixels_y))
65}
66
67pub fn mouse_delta_position() -> Vec2 {
69 let context = get_context();
70
71 let current_position = mouse_position_local();
72 let last_position = context.last_mouse_position.unwrap_or(current_position);
73
74 last_position - current_position
76}
77
78pub fn is_simulating_mouse_with_touch() -> bool {
81 get_context().simulate_mouse_with_touch
82}
83
84pub fn simulate_mouse_with_touch(option: bool) {
87 get_context().simulate_mouse_with_touch = option;
88}
89
90pub fn touches() -> Vec<Touch> {
92 get_context().touches.values().cloned().collect()
93}
94
95pub fn touches_local() -> Vec<Touch> {
97 get_context()
98 .touches
99 .values()
100 .map(|touch| {
101 let mut touch = touch.clone();
102 touch.position = convert_to_local(touch.position);
103 touch
104 })
105 .collect()
106}
107
108pub fn mouse_wheel() -> (f32, f32) {
109 let context = get_context();
110
111 (context.mouse_wheel.x, context.mouse_wheel.y)
112}
113
114pub fn is_key_pressed(key_code: KeyCode) -> bool {
116 let context = get_context();
117
118 context.keys_pressed.contains(&key_code)
119}
120
121pub fn is_key_down(key_code: KeyCode) -> bool {
123 let context = get_context();
124
125 context.keys_down.contains(&key_code)
126}
127
128pub fn is_key_released(key_code: KeyCode) -> bool {
130 let context = get_context();
131
132 context.keys_released.contains(&key_code)
133}
134
135pub fn is_any_key_down() -> bool {
137 let context = get_context();
138 context.keys_down.len() > 0
139}
140
141pub fn get_char_pressed() -> Option<char> {
144 let context = get_context();
145
146 context.chars_pressed_queue.pop()
147}
148
149pub(crate) fn get_char_pressed_ui() -> Option<char> {
150 let context = get_context();
151
152 context.chars_pressed_ui_queue.pop()
153}
154
155pub fn get_last_key_pressed() -> Option<KeyCode> {
157 let context = get_context();
158 context.keys_pressed.iter().next().cloned()
160}
161
162pub fn get_keys_pressed() -> HashSet<KeyCode> {
163 let context = get_context();
164 context.keys_pressed.clone()
165}
166
167pub fn get_keys_down() -> HashSet<KeyCode> {
168 let context = get_context();
169 context.keys_down.clone()
170}
171
172pub fn get_keys_released() -> HashSet<KeyCode> {
173 let context = get_context();
174 context.keys_released.clone()
175}
176
177pub fn clear_input_queue() {
179 let context = get_context();
180 context.chars_pressed_queue.clear();
181 context.chars_pressed_ui_queue.clear();
182}
183
184pub fn is_mouse_button_down(btn: MouseButton) -> bool {
186 let context = get_context();
187
188 context.mouse_down.contains(&btn)
189}
190
191pub fn is_mouse_button_pressed(btn: MouseButton) -> bool {
193 let context = get_context();
194
195 context.mouse_pressed.contains(&btn)
196}
197
198pub fn is_mouse_button_released(btn: MouseButton) -> bool {
200 let context = get_context();
201
202 context.mouse_released.contains(&btn)
203}
204
205fn convert_to_local(pixel_pos: Vec2) -> Vec2 {
207 Vec2::new(pixel_pos.x / screen_width(), pixel_pos.y / screen_height()) * 2.0
208 - Vec2::new(1.0, 1.0)
209}
210
211pub fn prevent_quit() {
213 get_context().prevent_quit_event = true;
214}
215
216pub fn is_quit_requested() -> bool {
218 get_context().quit_requested
219}
220
221pub fn get_dropped_files() -> Vec<DroppedFile> {
223 get_context().dropped_files()
224}
225
226pub mod utils {
230 use crate::get_context;
231
232 pub fn register_input_subscriber() -> usize {
234 let context = get_context();
235
236 context.input_events.push(vec![]);
237
238 context.input_events.len() - 1
239 }
240
241 pub fn repeat_all_miniquad_input<T: miniquad::EventHandler>(t: &mut T, subscriber: usize) {
243 let context = get_context();
244
245 for event in &context.input_events[subscriber] {
246 event.repeat(t);
247 }
248 context.input_events[subscriber].clear();
249 }
250}