|
- use std::collections::HashSet;
-
- use glutin::{
- event::{
- ElementState, Event, KeyboardInput, MouseScrollDelta, WindowEvent as GlutinWindowEvent,
- },
- event_loop::{ControlFlow, EventLoop},
- platform::desktop::EventLoopExtDesktop,
- };
- use shrev::{EventChannel, ReaderId};
- use space_crush_common::misc::{LogResult, WorldHelper};
- use specs::World;
-
- use crate::{misc::Window, Error};
-
- pub use glutin::event::{MouseButton, VirtualKeyCode};
-
- pub struct Events {
- keys: HashSet<VirtualKeyCode>,
- event_loop: EventLoop<()>,
- mouse_pos: Option<(f64, f64)>,
- mouse_lock: Option<(f64, f64)>,
- control_event_id: ReaderId<ControlEvent>,
- }
-
- impl Events {
- pub fn new(world: &mut World) -> Result<Self, Error> {
- world.insert(EventChannel::<ControlEvent>::default());
- world.insert(EventChannel::<MouseEvent>::default());
- world.insert(EventChannel::<WindowEvent>::default());
- world.insert(EventChannel::<KeyboardEvent>::default());
-
- let control_event_id = world.register_event_reader::<ControlEvent>()?;
-
- Ok(Self {
- keys: HashSet::new(),
- event_loop: EventLoop::new(),
- mouse_pos: None,
- mouse_lock: None,
- control_event_id,
- })
- }
- }
-
- impl Events {
- pub fn handle(&self) -> &EventLoop<()> {
- &self.event_loop
- }
-
- pub fn process(&mut self, world: &World, window: &Window) {
- let control_events = world.fetch::<EventChannel<ControlEvent>>();
- let mut mouse_events = world.fetch_mut::<EventChannel<MouseEvent>>();
- let mut window_events = world.fetch_mut::<EventChannel<WindowEvent>>();
- let mut keyboard_events = world.fetch_mut::<EventChannel<KeyboardEvent>>();
-
- let keys = &mut self.keys;
- let mouse_pos = &mut self.mouse_pos;
- let event_loop = &mut self.event_loop;
- let mouse_lock = &mut self.mouse_lock;
-
- let events = control_events.read(&mut self.control_event_id);
- for event in events {
- match event {
- ControlEvent::LockMouse => {
- *mouse_lock = *mouse_pos;
- window
- .set_mouse_locked(true)
- .warn("Unable to lock mouse to window");
- }
- ControlEvent::UnlockMouse => {
- *mouse_lock = None;
- window
- .set_mouse_locked(false)
- .warn("Unable to lock mouse to window");
- }
- }
- }
-
- let mut has_mouse_moved = false;
- event_loop.run_return(|event, _target, flow_control| {
- *flow_control = ControlFlow::Poll;
-
- match event {
- Event::MainEventsCleared | Event::RedrawRequested(_) => {
- *flow_control = ControlFlow::Exit;
- }
- Event::WindowEvent { event, .. } => match event {
- /* Mouse Events */
- GlutinWindowEvent::CursorMoved { position, .. } => {
- if mouse_lock.is_none() {
- mouse_events
- .single_write(MouseEvent::Move(position.x as _, position.y as _));
- }
-
- if let Some((x, y)) = mouse_pos {
- let dx = position.x - *x;
- let dy = position.y - *y;
-
- mouse_events.single_write(MouseEvent::Delta(dx as _, dy as _));
- }
-
- has_mouse_moved = true;
- *mouse_pos = Some((position.x as _, position.y as _));
- }
- GlutinWindowEvent::MouseInput {
- state: ElementState::Pressed,
- button,
- ..
- } => {
- mouse_events.single_write(MouseEvent::ButtonDown(button));
- }
- GlutinWindowEvent::MouseInput {
- state: ElementState::Released,
- button,
- ..
- } => {
- mouse_events.single_write(MouseEvent::ButtonUp(button));
- }
- GlutinWindowEvent::MouseWheel {
- delta: MouseScrollDelta::LineDelta(x, y),
- ..
- } => {
- if x != 0.0 {
- mouse_events.single_write(MouseEvent::ScrollX(x));
- }
-
- if y != 0.0 {
- mouse_events.single_write(MouseEvent::ScrollY(y));
- }
- }
- GlutinWindowEvent::CursorLeft { .. } => {
- *mouse_pos = None;
- }
-
- /* Key Event */
- GlutinWindowEvent::KeyboardInput {
- input:
- KeyboardInput {
- state: ElementState::Pressed,
- virtual_keycode: Some(key),
- ..
- },
- ..
- } => {
- if keys.insert(key) {
- keyboard_events.single_write(KeyboardEvent::KeyDown(key));
- }
-
- keyboard_events.single_write(KeyboardEvent::KeyPress(key));
- }
- GlutinWindowEvent::KeyboardInput {
- input:
- KeyboardInput {
- state: ElementState::Released,
- virtual_keycode: Some(key),
- ..
- },
- ..
- } => {
- if keys.remove(&key) {
- keyboard_events.single_write(KeyboardEvent::KeyUp(key));
- }
- }
-
- /* Window Event */
- GlutinWindowEvent::Resized(pos) => {
- window_events.single_write(WindowEvent::Resize(pos.width, pos.height));
- }
- GlutinWindowEvent::CloseRequested => {
- window_events.single_write(WindowEvent::Close);
- }
-
- /* Ignore */
- _ => (),
- },
- _ => (),
- }
- });
-
- if let Some((x, y)) = self.mouse_lock {
- if has_mouse_moved {
- window.set_mouse_pos(x, y).warn("Unable to set mouse pos");
- self.mouse_pos = Some((x, y));
- }
- }
- }
- }
-
- pub enum ControlEvent {
- LockMouse,
- UnlockMouse,
- }
-
- pub enum WindowEvent {
- Resize(u32, u32),
- Close,
- }
-
- pub enum MouseEvent {
- Move(f32, f32),
- Delta(f32, f32),
- ButtonDown(MouseButton),
- ButtonUp(MouseButton),
- ScrollX(f32),
- ScrollY(f32),
- }
-
- pub enum KeyboardEvent {
- KeyUp(VirtualKeyCode),
- KeyDown(VirtualKeyCode),
- KeyPress(VirtualKeyCode),
- }
|