wasm_game_lib/inputs/
mouse.rs1use core::convert::TryFrom;
2use crate::elog;
3
4#[derive(Debug)]
6pub enum MouseEvent {
7 Click(u32, u32),
9 DoubleClick(u32, u32),
10 Move(u32, u32),
11 Enter(u32, u32),
12 Leave(u32, u32),
13 Up(Button, u32, u32),
14 Down(Button, u32, u32),
15 Scroll(f64, f64, f64, DeltaMode),
17}
18
19use lazy_static::lazy_static;
20use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
21use std::sync::Mutex;
22
23#[derive(Debug)]
24pub enum DeltaMode {
25 Pixel,
26 Line,
27 Page,
28}
29
30impl TryFrom<u32> for DeltaMode {
31 type Error = u32;
32
33 fn try_from(number: u32) -> Result<Self, u32> {
34 match number {
35 0 => Ok(DeltaMode::Pixel),
36 1 => Ok(DeltaMode::Line),
37 2 => Ok(DeltaMode::Page),
38 n => Err(n),
39 }
40 }
41}
42
43#[derive(Debug)]
45pub enum Button {
46 Main,
48 Auxiliary,
50 Secondary,
52 Fourth,
54 Fifth
56}
57
58impl TryFrom<i16> for Button {
59 type Error = i16;
60
61 fn try_from(number: i16) -> Result<Self, i16> {
62 match number {
63 0 => Ok(Button::Main),
64 1 => Ok(Button::Auxiliary),
65 2 => Ok(Button::Secondary),
66 3 => Ok(Button::Fourth),
67 4 => Ok(Button::Fifth),
68 n => Err(n),
69 }
70 }
71}
72
73lazy_static! {
74 static ref IS_RECORDING_MOUSE_EVENTS: AtomicBool = AtomicBool::new(false);
75 static ref IS_MAIN_BUTTON_PRESSED: AtomicBool = AtomicBool::new(false);
76 static ref IS_AUXILIARY_BUTTON_PRESSED: AtomicBool = AtomicBool::new(false);
77 static ref IS_SECONDARY_BUTTON_PRESSED: AtomicBool = AtomicBool::new(false);
78 static ref IS_FOURTH_BUTTON_PRESSED: AtomicBool = AtomicBool::new(false);
79 static ref IS_FIFTH_BUTTON_PRESSED: AtomicBool = AtomicBool::new(false);
80 static ref IS_MOUSE_IN_CANVAS: AtomicBool = AtomicBool::new(true);
81 static ref MOUSE_POSITION: Mutex<(u32, u32)> = Mutex::new((0,0));
82}
83
84pub fn are_mouse_events_recorded() -> bool {
86 IS_RECORDING_MOUSE_EVENTS.load(Relaxed)
87}
88
89pub fn is_mouse_in_canvas() -> bool {
92 IS_MOUSE_IN_CANVAS.load(Relaxed)
93}
94
95pub fn start_recording_mouse_events() {
100 use wasm_bindgen::{prelude::*, JsCast};
101 use web_sys::window;
102
103 if !are_mouse_events_recorded() {
104 let window = window().unwrap();
105
106 let event = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
107 match event.button() {
108 0 => IS_MAIN_BUTTON_PRESSED.store(true, Relaxed),
109 1 => IS_AUXILIARY_BUTTON_PRESSED.store(true, Relaxed),
110 2 => IS_SECONDARY_BUTTON_PRESSED.store(true, Relaxed),
111 3 => IS_FOURTH_BUTTON_PRESSED.store(true, Relaxed),
112 4 => IS_FIFTH_BUTTON_PRESSED.store(true, Relaxed),
113 n => elog!("Unknown mouse button pressed: {}", n),
114 }
115 }) as Box<dyn FnMut(web_sys::MouseEvent)>);
116 window
117 .add_event_listener_with_callback("mousedown", event.as_ref().unchecked_ref())
118 .unwrap();
119 event.forget();
120
121 let event = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
122 match event.button() {
123 0 => IS_MAIN_BUTTON_PRESSED.store(false, Relaxed),
124 1 => IS_AUXILIARY_BUTTON_PRESSED.store(false, Relaxed),
125 2 => IS_SECONDARY_BUTTON_PRESSED.store(false, Relaxed),
126 3 => IS_FOURTH_BUTTON_PRESSED.store(false, Relaxed),
127 4 => IS_FIFTH_BUTTON_PRESSED.store(false, Relaxed),
128 n => elog!("Unknown mouse button released: {}", n),
129 }
130 }) as Box<dyn FnMut(web_sys::MouseEvent)>);
131 window
132 .add_event_listener_with_callback("mouseup", event.as_ref().unchecked_ref())
133 .unwrap();
134 event.forget();
135
136 let event = Closure::wrap(Box::new(move |_event: web_sys::MouseEvent| {
137 IS_MOUSE_IN_CANVAS.store(true, Relaxed);
138 }) as Box<dyn FnMut(web_sys::MouseEvent)>);
139 window
140 .add_event_listener_with_callback("mouseenter", event.as_ref().unchecked_ref())
141 .unwrap();
142 event.forget();
143
144 let event = Closure::wrap(Box::new(move |_event: web_sys::MouseEvent| {
145 IS_MOUSE_IN_CANVAS.store(false, Relaxed);
146 }) as Box<dyn FnMut(web_sys::MouseEvent)>);
147 window
148 .add_event_listener_with_callback("mouseleave", event.as_ref().unchecked_ref())
149 .unwrap();
150 event.forget();
151
152 let event = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
153 *MOUSE_POSITION.lock().unwrap() = (event.client_x() as u32, event.client_y() as u32);
154 }) as Box<dyn FnMut(web_sys::MouseEvent)>);
155 window
156 .add_event_listener_with_callback("mousemove", event.as_ref().unchecked_ref())
157 .unwrap();
158 event.forget();
159
160 IS_RECORDING_MOUSE_EVENTS.store(true, Relaxed);
161 } else {
162 elog!("Your program is calling start_recording_mouse_events() multiple times! That's bad!");
163 }
164}
165
166pub fn is_pressed(button: Button) -> bool {
169 match button {
170 Button::Main => IS_MAIN_BUTTON_PRESSED.load(Relaxed),
171 Button::Auxiliary => IS_AUXILIARY_BUTTON_PRESSED.load(Relaxed),
172 Button::Secondary => IS_SECONDARY_BUTTON_PRESSED.load(Relaxed),
173 Button::Fourth => IS_FOURTH_BUTTON_PRESSED.load(Relaxed),
174 Button::Fifth => IS_FIFTH_BUTTON_PRESSED.load(Relaxed),
175 }
176}
177
178pub fn get_mouse_position() -> (u32, u32) {
181 *MOUSE_POSITION.lock().unwrap()
182}