oxygengine_input_device_web/
mouse.rs1use backend::closure::WebClosure;
2use core::{ecs::Universe, Scalar};
3use input::device::InputDevice;
4use std::{any::Any, cell::Cell, rc::Rc};
5use wasm_bindgen::{prelude::*, JsCast};
6use web_sys::*;
7
8pub struct WebMouseInputDevice {
9 element: EventTarget,
10 position: Rc<Cell<(Scalar, Scalar)>>,
11 left_button: Rc<Cell<bool>>,
12 right_button: Rc<Cell<bool>>,
13 middle_button: Rc<Cell<bool>>,
14 mouse_down_closure: WebClosure,
15 mouse_up_closure: WebClosure,
16 mouse_move_closure: WebClosure,
17}
18
19unsafe impl Send for WebMouseInputDevice {}
20unsafe impl Sync for WebMouseInputDevice {}
21
22impl WebMouseInputDevice {
23 pub fn new(element: EventTarget) -> Self {
24 Self {
25 element,
26 position: Default::default(),
27 left_button: Default::default(),
28 right_button: Default::default(),
29 middle_button: Default::default(),
30 mouse_down_closure: Default::default(),
31 mouse_up_closure: Default::default(),
32 mouse_move_closure: Default::default(),
33 }
34 }
35}
36
37impl InputDevice for WebMouseInputDevice {
38 fn name(&self) -> &str {
39 "mouse"
40 }
41
42 fn on_register(&mut self) {
43 {
44 let left_button = self.left_button.clone();
45 let right_button = self.right_button.clone();
46 let middle_button = self.middle_button.clone();
47 let closure = Closure::wrap(Box::new(move |event: MouseEvent| match event.button() {
48 0 => left_button.set(true),
49 2 => right_button.set(true),
50 1 => middle_button.set(true),
51 _ => {}
52 }) as Box<dyn FnMut(_)>);
53 self.element
54 .add_event_listener_with_callback("mousedown", closure.as_ref().unchecked_ref())
55 .unwrap();
56 self.mouse_down_closure = WebClosure::acquire(closure);
57 }
58 {
59 let left_button = self.left_button.clone();
60 let right_button = self.right_button.clone();
61 let middle_button = self.middle_button.clone();
62 let closure = Closure::wrap(Box::new(move |event: MouseEvent| match event.button() {
63 0 => left_button.set(false),
64 2 => right_button.set(false),
65 1 => middle_button.set(false),
66 _ => {}
67 }) as Box<dyn FnMut(_)>);
68 self.element
69 .add_event_listener_with_callback("mouseup", closure.as_ref().unchecked_ref())
70 .unwrap();
71 self.mouse_up_closure = WebClosure::acquire(closure);
72 }
73 {
74 let position = self.position.clone();
75 let closure = Closure::wrap(Box::new(move |event: MouseEvent| {
76 position.set((event.client_x() as Scalar, event.client_y() as Scalar));
77 }) as Box<dyn FnMut(_)>);
78 self.element
79 .add_event_listener_with_callback("mousemove", closure.as_ref().unchecked_ref())
80 .unwrap();
81 self.mouse_move_closure = WebClosure::acquire(closure);
82 }
83 }
84
85 fn on_unregister(&mut self) {
86 self.mouse_down_closure.release();
87 self.mouse_up_closure.release();
88 self.mouse_move_closure.release();
89 }
90
91 fn process(&mut self, _: &mut Universe) {}
92
93 fn query_axis(&self, name: &str) -> Option<Scalar> {
94 match name {
95 "x" => Some(self.position.get().0),
96 "y" => Some(self.position.get().1),
97 _ => None,
98 }
99 }
100
101 fn query_trigger(&self, name: &str) -> Option<bool> {
102 match name {
103 "left" => Some(self.left_button.get()),
104 "right" => Some(self.right_button.get()),
105 "middle" => Some(self.middle_button.get()),
106 _ => None,
107 }
108 }
109
110 fn query_text(&self) -> Option<String> {
111 None
112 }
113
114 fn as_any(&self) -> &dyn Any {
115 self
116 }
117}