Based on : Game Development with Rust and WebAssembly by Eric Smith (Paytonrules)
pub struct KeyState {
pressed_keys: HashMap<String, web_sys::KeyboardEvent>,
}
impl KeyState {
fn new() -> Self {
return KeyState {
pressed_keys: HashMap::new(),
};
}
pub fn is_pressed(&self, code: &str) -> bool {
self.pressed_keys.contains_key(code)
}
fn set_pressed(&mut self, code: &str, event: web_sys::KeyboardEvent) {
self.pressed_keys.insert(code.into(), event);
}
fn set_released(&mut self, code: &str) {
self.pressed_keys.remove(code.into());
}
}
enum KeyPress {
KeyUp(web_sys::KeyboardEvent),
KeyDown(web_sys::KeyboardEvent),
}
fn process_input(state: &mut KeyState, keyevent_receiver: &mut UnboundedReceiver<KeyPress>) {
loop {
match keyevent_receiver.try_next() {
Ok(None) => break,
Err(_err) => break,
Ok(Some(evt)) => match evt {
KeyPress::KeyUp(evt) => state.set_released(&evt.code()),
KeyPress::KeyDown(evt) => state.set_pressed(&evt.code(), evt),
},
};
}
}
fn prepare_input() -> Result<UnboundedReceiver<KeyPress>> {
let (keydown_sender, keyevent_receiver) = unbounded();
let keydown_sender = Rc::new(RefCell::new(keydown_sender));
let keyup_sender = Rc::clone(&keydown_sender);
let onkeydown = browser::closure_wrap(Box::new(move |keycode: web_sys::KeyboardEvent| {
keydown_sender
.borrow_mut()
.start_send(KeyPress::KeyDown(keycode));
}) as Box<dyn FnMut(web_sys::KeyboardEvent)>);
let onkeyup = browser::closure_wrap(Box::new(move |keycode: web_sys::KeyboardEvent| {
keyup_sender
.borrow_mut()
.start_send(KeyPress::KeyUp(keycode));
}) as Box<dyn FnMut(web_sys::KeyboardEvent)>);
browser::canvas()?.set_onkeydown(Some(onkeydown.as_ref().unchecked_ref()));
browser::canvas()?.set_onkeyup(Some(onkeyup.as_ref().unchecked_ref()));
onkeydown.forget();
onkeyup.forget();
Ok(keyevent_receiver)
}