wasm_game_lib/inputs/
event.rs

1/// This module contains every event type.
2/// It is intended to be used in the [init_with_events method](../../../graphics/window/struct.Window.html#method.init_with_events).
3#[allow(clippy::unreadable_literal)]
4pub mod types {
5    /// Events related to the mouse
6    pub const MOUSE_EVENT: u8 =     0b00000001;
7    /// Events related to the keyboard
8    pub const KEYBOARD_EVENT: u8 =  0b00000010;
9    /// Event fired when the size of the window change
10    pub const RESIZE_EVENT: u8 =    0b00000100;
11    /// Events fired when the window lost or gain focus
12    pub const FOCUS_EVENT: u8 =     0b00001000;
13    /// Joysticks are not supported for now
14    pub const JOYSTICK_EVENT: u8 =  0b00010000;
15}
16
17use super::mouse::*;
18use super::keyboard::*;
19use super::joystick::*;
20use crate::elog;
21
22/// An enum containing more specific enums.
23#[derive(Debug)]
24pub enum Event {
25    /// Event is a mouse event
26    MouseEvent(MouseEvent),
27    /// Event is a keyboard event
28    KeyboardEvent(KeyboardEvent),
29    /// The size of the window changed, contains the new size
30    ResizeEvent(u32, u32),
31    /// The window got or lost focus.
32    /// The bool is set to true if the tab has the focus after the modification.
33    FocusEvent(bool),
34    /// Joysticks are unsupported
35    JoystickEvent(JoystickEvent)
36}
37
38use std::rc::Rc;
39use std::collections::VecDeque;
40use std::cell::RefCell;
41use wasm_bindgen::{prelude::*, JsCast};
42use web_sys::{window, Window as WebSysWindow};
43use std::convert::TryFrom;
44
45/// The struct which tracks events.
46/// You can get this struct with the [poll_event() method](../../graphics/window/struct.Window.html#method.poll_event), or by creating it [manually](#method.new).
47pub struct EventManager {
48    window: WebSysWindow,
49    events: Rc<RefCell<VecDeque<Event>>>
50}
51
52impl Default for EventManager {
53    fn default() -> Self {
54        Self::new()
55    }
56}
57
58impl EventManager {
59    /// Create an event manager.
60    /// It will not record events if you don't call the appropriate methods.
61    pub fn new() -> Self {
62        EventManager {
63            window: window().unwrap(),
64            events: Rc::new(RefCell::new(VecDeque::new()))
65        }
66    }
67
68    /// The event manager will start recording mouse events.
69    /// This can't be stopped!
70    pub fn start_recording_mouse_events(&mut self) {
71        use crate::inputs::mouse::*;
72
73        let events2 = Rc::clone(&self.events);
74        let click = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
75            events2.borrow_mut().push_back(Event::MouseEvent(MouseEvent::Click(event.client_x() as u32, event.client_y() as u32)));
76        }) as Box<dyn FnMut(web_sys::MouseEvent)>);
77        self.window
78            .add_event_listener_with_callback("click", click.as_ref().unchecked_ref())
79            .unwrap();
80        click.forget();
81
82        let events2 = Rc::clone(&self.events);
83        let event = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
84            events2.borrow_mut().push_back(Event::MouseEvent(MouseEvent::DoubleClick(event.client_x() as u32, event.client_y() as u32)));
85        }) as Box<dyn FnMut(web_sys::MouseEvent)>);
86        self.window
87            .add_event_listener_with_callback("dblclick", event.as_ref().unchecked_ref())
88            .unwrap();
89        event.forget();
90
91        let events2 = Rc::clone(&self.events);
92        let event = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
93            match Button::try_from(event.button()) {
94                Ok(button) => events2.borrow_mut().push_back(Event::MouseEvent(MouseEvent::Down(button, event.client_x() as u32, event.client_y() as u32))),
95                Err(n) => elog!("Unknown mouse button pressed: {}", n),
96            }       
97        }) as Box<dyn FnMut(web_sys::MouseEvent)>);
98        self.window
99            .add_event_listener_with_callback("mousedown", event.as_ref().unchecked_ref())
100            .unwrap();
101        event.forget();
102
103        let events2 = Rc::clone(&self.events);
104        let event = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
105            match Button::try_from(event.button()) {
106                Ok(button) => events2.borrow_mut().push_back(Event::MouseEvent(MouseEvent::Up(button, event.client_x() as u32, event.client_y() as u32))),
107                Err(n) => elog!("Unknown mouse button released: {}", n),
108            }
109        }) as Box<dyn FnMut(web_sys::MouseEvent)>);
110        self.window
111            .add_event_listener_with_callback("mouseup", event.as_ref().unchecked_ref())
112            .unwrap();
113        event.forget();
114
115        let events2 = Rc::clone(&self.events);
116        let event = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
117            events2.borrow_mut().push_back(Event::MouseEvent(MouseEvent::Enter(event.client_x() as u32, event.client_y() as u32)));            
118        }) as Box<dyn FnMut(web_sys::MouseEvent)>);
119        self.window
120            .add_event_listener_with_callback("mouseenter", event.as_ref().unchecked_ref())
121            .unwrap();
122        event.forget();
123
124        let events2 = Rc::clone(&self.events);
125        let event = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
126            events2.borrow_mut().push_back(Event::MouseEvent(MouseEvent::Leave(event.client_x() as u32, event.client_y() as u32)));            
127        }) as Box<dyn FnMut(web_sys::MouseEvent)>);
128        self.window
129            .add_event_listener_with_callback("mouseleave", event.as_ref().unchecked_ref())
130            .unwrap();
131        event.forget();
132
133        let events2 = Rc::clone(&self.events);
134        let event = Closure::wrap(Box::new(move |event: web_sys::MouseEvent| {
135            events2.borrow_mut().push_back(Event::MouseEvent(MouseEvent::Move(event.client_x() as u32, event.client_y() as u32)));
136        }) as Box<dyn FnMut(web_sys::MouseEvent)>);
137        self.window
138            .add_event_listener_with_callback("mousemove", event.as_ref().unchecked_ref())
139            .unwrap();
140        event.forget();
141
142        let events2 = Rc::clone(&self.events);
143        let event = Closure::wrap(Box::new(move |event: web_sys::WheelEvent| {
144            match DeltaMode::try_from(event.delta_mode()) {
145                Ok(mode) => events2.borrow_mut().push_back(Event::MouseEvent(MouseEvent::Scroll(event.delta_x(), event.delta_y(), event.delta_z(), mode))),
146                Err(n) => elog!("Unknown mouse movement: {}", n),
147            }
148        }) as Box<dyn FnMut(web_sys::WheelEvent)>);
149        self.window
150            .add_event_listener_with_callback("wheel", event.as_ref().unchecked_ref())
151            .unwrap();
152        event.forget();
153    }
154
155    /// The event manager will start recording keyboard events.
156    /// This can't be stopped!
157    pub fn start_recording_keyboard_events(&mut self) {
158        use crate::inputs::keyboard::*;
159
160        let events2 = Rc::clone(&self.events);
161        let click = Closure::wrap(Box::new(move |event: web_sys::KeyboardEvent| {
162            events2.borrow_mut().push_back(Event::KeyboardEvent(KeyboardEvent::Up(Key::from(event.key_code()))))
163        }) as Box<dyn FnMut(web_sys::KeyboardEvent)>);
164        self.window
165            .add_event_listener_with_callback("keyup", click.as_ref().unchecked_ref())
166            .unwrap();
167        click.forget();
168
169        let events2 = Rc::clone(&self.events);
170        let event = Closure::wrap(Box::new(move |event: web_sys::KeyboardEvent| {
171            events2.borrow_mut().push_back(Event::KeyboardEvent(KeyboardEvent::Down(Key::from(event.key_code()))));
172            
173        }) as Box<dyn FnMut(web_sys::KeyboardEvent)>);
174        self.window
175            .add_event_listener_with_callback("keydown", event.as_ref().unchecked_ref())
176            .unwrap();
177        event.forget();
178    }
179
180    /// The event manager will start recording focus events.
181    /// This can't be stopped!
182    pub fn start_recording_focus_events(&mut self) {
183        let events2 = Rc::clone(&self.events);
184        let event = Closure::wrap(Box::new(move || {
185            events2.borrow_mut().push_back(Event::FocusEvent(true))
186        }) as Box<dyn FnMut()>);
187        self.window
188            .add_event_listener_with_callback("focus", event.as_ref().unchecked_ref())
189            .unwrap();
190        event.forget();
191
192        let events2 = Rc::clone(&self.events);
193        let event = Closure::wrap(Box::new(move || {
194            events2.borrow_mut().push_back(Event::FocusEvent(false));
195            
196        }) as Box<dyn FnMut()>);
197        self.window
198            .add_event_listener_with_callback("blur", event.as_ref().unchecked_ref())
199            .unwrap();
200        event.forget();
201    }
202
203    /// The event manager will start recording size events.
204    /// This can't be stopped!
205    pub fn start_recording_size_events(&mut self) {
206        let events2 = Rc::clone(&self.events);
207        let event = Closure::wrap(Box::new(move || {
208            let width = window().unwrap().document().unwrap().document_element().unwrap().client_width() as u32;
209            let height = window().unwrap().document().unwrap().document_element().unwrap().client_height() as u32;
210            events2.borrow_mut().push_back(Event::ResizeEvent(width, height));
211        }) as Box<dyn FnMut()>);
212        self.window
213            .add_event_listener_with_callback("resize", event.as_ref().unchecked_ref())
214            .unwrap();
215        event.forget();
216    }
217}
218
219impl Iterator for EventManager {
220    type Item = Event;
221
222    fn next(&mut self) -> Option<Self::Item> {
223        self.events.borrow_mut().pop_front()
224    }
225}