sylasteven_system_input_default/
lib.rs1#![deny(missing_docs)]
2use sylasteven as engine;
7
8use glutin::{EventsLoop, GlContext, GlWindow};
9
10pub use glutin::{ModifiersState as Modifiers, MouseButton, VirtualKeyCode as KeyCode};
11
12pub enum InputEvent {
14 Resize {
16 width: u32,
18 height: u32,
20 },
21 Key {
23 keycode: KeyCode,
25 modifiers: Modifiers,
27 down: bool,
29 },
30 TextInput(char),
32 MouseClick {
34 button: MouseButton,
36 modifiers: Modifiers,
38 down: bool,
40 },
41 MouseMove {
43 x: f32,
45 y: f32,
47 },
48 MouseWheel(f32),
50 File {
52 dropped: bool,
54 path: std::path::PathBuf,
56 },
57 Quit,
59}
60
61pub struct Input {
63 events_loop: EventsLoop,
64}
65
66impl Input {
67 pub fn new(name: &str, w: u32, h: u32) -> (Self, GlWindow) {
69 let events_loop = glutin::EventsLoop::new();
70 let window = glutin::WindowBuilder::new()
71 .with_title(name)
72 .with_dimensions(w, h);
73 let context = glutin::ContextBuilder::new()
74 .with_vsync(true)
75 .with_multisampling(4)
76 .with_srgb(false);
77 let gl_window = GlWindow::new(window, context, &events_loop).unwrap();
78
79 unsafe {
80 gl_window.make_current().unwrap();
81 gl::load_with(|symbol| gl_window.get_proc_address(symbol) as *const _);
82 gl::ClearColor(0.0, 0.0, 0.0, 1.0);
83 }
84
85 (Self { events_loop }, gl_window)
86 }
87}
88
89use crate::engine::{Handler, System};
90
91impl<H: Handler> System<H> for Input
92where
93 H::Event: From<InputEvent>,
94{
95 fn process(&mut self, handler: &mut H) {
96 let Self { events_loop } = self;
97 events_loop.poll_events(|event| {
98 if let Some(event) = match event {
99 glutin::Event::WindowEvent { event, .. } => match event {
100 glutin::WindowEvent::CloseRequested => Some(InputEvent::Quit),
101 glutin::WindowEvent::Resized(width, height) => {
102 Some(InputEvent::Resize { width, height })
103 }
104 glutin::WindowEvent::KeyboardInput {
105 input:
106 glutin::KeyboardInput {
107 state,
108 virtual_keycode: Some(keycode),
109 modifiers,
110 ..
111 },
112 ..
113 } => {
114 use glutin::ElementState::*;
115 let down = match state {
116 Pressed => true,
117 Released => false,
118 };
119 Some(InputEvent::Key {
120 keycode,
121 down,
122 modifiers,
123 })
124 }
125
126 glutin::WindowEvent::ReceivedCharacter(char) => {
127 Some(InputEvent::TextInput(char))
128 }
129
130 glutin::WindowEvent::DroppedFile(path) => Some(InputEvent::File {
131 dropped: true,
132 path,
133 }),
134
135 glutin::WindowEvent::HoveredFile(path) => Some(InputEvent::File {
136 dropped: false,
137 path,
138 }),
139
140 glutin::WindowEvent::MouseInput {
141 state,
142 button,
143 modifiers,
144 ..
145 } => {
146 use glutin::ElementState::*;
147 let down = match state {
148 Pressed => true,
149 Released => false,
150 };
151 Some(InputEvent::MouseClick {
152 button,
153 down,
154 modifiers,
155 })
156 }
157 glutin::WindowEvent::MouseWheel { delta, .. } => {
158 use glutin::MouseScrollDelta::*;
159 let delta = match delta {
160 LineDelta(_, delta) => delta,
161 PixelDelta(_, delta) => delta,
162 };
163 Some(InputEvent::MouseWheel(delta))
164 }
165 glutin::WindowEvent::CursorMoved { position, .. } => {
166 Some(InputEvent::MouseMove {
167 x: position.0 as f32,
168 y: position.1 as f32,
169 })
170 }
171 _ => None,
172 },
173 _ => None,
174 } {
175 handler.handle(event.into());
176 }
177 });
178 }
179}