use gilrs;
use winit::{self, dpi};
pub use winit::MouseButton;
pub use gilrs::Axis;
pub use gilrs::Button;
pub mod winit_event {
pub use super::winit::{
DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, MouseScrollDelta,
TouchPhase, WindowEvent,
};
}
use self::winit_event::*;
pub use winit::EventsLoop;
use crate::context::Context;
use crate::error::GameResult;
pub use crate::input::keyboard::{KeyCode, KeyMods};
pub trait EventHandler {
fn update(&mut self, _ctx: &mut Context) -> GameResult;
fn draw(&mut self, _ctx: &mut Context) -> GameResult;
fn mouse_button_down_event(
&mut self,
_ctx: &mut Context,
_button: MouseButton,
_x: f32,
_y: f32,
) {
}
fn mouse_button_up_event(
&mut self,
_ctx: &mut Context,
_button: MouseButton,
_x: f32,
_y: f32,
) {
}
fn mouse_motion_event(&mut self, _ctx: &mut Context, _x: f32, _y: f32, _dx: f32, _dy: f32) {}
fn mouse_wheel_event(&mut self, _ctx: &mut Context, _x: f32, _y: f32) {}
fn key_down_event(
&mut self,
ctx: &mut Context,
keycode: KeyCode,
_keymods: KeyMods,
_repeat: bool,
) {
if keycode == KeyCode::Escape {
super::quit(ctx);
}
}
fn key_up_event(&mut self, _ctx: &mut Context, _keycode: KeyCode, _keymods: KeyMods) {}
fn text_input_event(&mut self, _ctx: &mut Context, _character: char) {}
fn controller_button_down_event(&mut self, _ctx: &mut Context, _btn: Button, _id: usize) {}
fn controller_button_up_event(&mut self, _ctx: &mut Context, _btn: Button, _id: usize) {}
fn controller_axis_event(&mut self, _ctx: &mut Context, _axis: Axis, _value: f32, _id: usize) {}
fn focus_event(&mut self, _ctx: &mut Context, _gained: bool) {}
fn quit_event(&mut self, _ctx: &mut Context) -> bool {
debug!("quit_event() callback called, quitting...");
false
}
fn resize_event(&mut self, _ctx: &mut Context, _width: f32, _height: f32) {}
}
pub fn run<S>(ctx: &mut Context, events_loop: &mut EventsLoop, state: &mut S) -> GameResult
where
S: EventHandler,
{
use crate::input::{keyboard, mouse};
while ctx.continuing {
ctx.timer_context.tick();
events_loop.poll_events(|event| {
let event = ctx.process_event(&event);
match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::Resized(dpi::LogicalSize { width, height }) => {
state.resize_event(ctx, width as f32, height as f32);
}
WindowEvent::CloseRequested => {
if !state.quit_event(ctx) {
super::quit(ctx);
}
}
WindowEvent::Focused(gained) => {
state.focus_event(ctx, gained);
}
WindowEvent::ReceivedCharacter(ch) => {
state.text_input_event(ctx, ch);
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(keycode),
modifiers,
..
},
..
} => {
let repeat = keyboard::is_key_repeated(ctx);
state.key_down_event(ctx, keycode, modifiers.into(), repeat);
}
WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Released,
virtual_keycode: Some(keycode),
modifiers,
..
},
..
} => {
state.key_up_event(ctx, keycode, modifiers.into());
}
WindowEvent::MouseWheel { delta, .. } => {
let (x, y) = match delta {
MouseScrollDelta::LineDelta(x, y) => (x, y),
MouseScrollDelta::PixelDelta(dpi::LogicalPosition { x, y }) => {
(x as f32, y as f32)
}
};
state.mouse_wheel_event(ctx, x, y);
}
WindowEvent::MouseInput {
state: element_state,
button,
..
} => {
let position = mouse::position(ctx);
match element_state {
ElementState::Pressed => {
state.mouse_button_down_event(ctx, button, position.x, position.y)
}
ElementState::Released => {
state.mouse_button_up_event(ctx, button, position.x, position.y)
}
}
}
WindowEvent::CursorMoved { .. } => {
let position = mouse::position(ctx);
let delta = mouse::delta(ctx);
state.mouse_motion_event(ctx, position.x, position.y, delta.x, delta.y);
}
x => {
trace!("ignoring window event {:?}", x);
}
},
Event::DeviceEvent { event, .. } => match event {
_ => (),
},
Event::Awakened => (),
Event::Suspended(_) => (),
}
});
if ctx.conf.modules.gamepad {
while let Some(gilrs::Event { id, event, .. }) = ctx.gamepad_context.next_event() {
match event {
gilrs::EventType::ButtonPressed(button, _) => {
state.controller_button_down_event(ctx, button, id);
}
gilrs::EventType::ButtonReleased(button, _) => {
state.controller_button_up_event(ctx, button, id);
}
gilrs::EventType::AxisChanged(axis, value, _) => {
state.controller_axis_event(ctx, axis, value, id);
}
_ => {}
}
}
}
state.update(ctx)?;
state.draw(ctx)?;
}
Ok(())
}