2019-01-07 21:10:31 +00:00
|
|
|
// Library
|
2019-01-11 17:30:13 +00:00
|
|
|
use glutin;
|
|
|
|
use gfx_window_glutin;
|
2019-01-12 01:14:58 +00:00
|
|
|
use vek::*;
|
2019-01-02 21:25:01 +00:00
|
|
|
|
2019-01-02 22:08:13 +00:00
|
|
|
// Crate
|
2019-01-07 21:10:31 +00:00
|
|
|
use crate::{
|
2019-01-11 23:18:34 +00:00
|
|
|
Error,
|
2019-01-11 17:30:13 +00:00
|
|
|
render::{
|
|
|
|
Renderer,
|
|
|
|
TgtColorFmt,
|
|
|
|
TgtDepthFmt,
|
|
|
|
},
|
2019-01-07 21:10:31 +00:00
|
|
|
};
|
2019-01-02 21:25:01 +00:00
|
|
|
|
|
|
|
pub struct Window {
|
2019-01-11 17:30:13 +00:00
|
|
|
events_loop: glutin::EventsLoop,
|
2019-01-07 21:10:31 +00:00
|
|
|
renderer: Renderer,
|
2019-01-23 22:21:47 +00:00
|
|
|
window: glutin::GlWindow,
|
|
|
|
cursor_grabbed: bool,
|
2019-01-02 21:25:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Window {
|
2019-01-11 23:18:34 +00:00
|
|
|
pub fn new() -> Result<Window, Error> {
|
2019-01-11 17:30:13 +00:00
|
|
|
let events_loop = glutin::EventsLoop::new();
|
2019-01-02 21:25:01 +00:00
|
|
|
|
2019-01-11 17:30:13 +00:00
|
|
|
let win_builder = glutin::WindowBuilder::new()
|
2019-01-07 21:10:31 +00:00
|
|
|
.with_title("Veloren (Voxygen)")
|
2019-01-11 17:30:13 +00:00
|
|
|
.with_dimensions(glutin::dpi::LogicalSize::new(800.0, 500.0))
|
2019-01-11 23:18:34 +00:00
|
|
|
.with_maximized(false);
|
2019-01-11 17:30:13 +00:00
|
|
|
|
|
|
|
let ctx_builder = glutin::ContextBuilder::new()
|
|
|
|
.with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 2)))
|
|
|
|
.with_vsync(true);
|
|
|
|
|
|
|
|
let (
|
|
|
|
window,
|
|
|
|
device,
|
|
|
|
factory,
|
|
|
|
tgt_color_view,
|
|
|
|
tgt_depth_view,
|
|
|
|
) = gfx_window_glutin::init::<TgtColorFmt, TgtDepthFmt>(
|
|
|
|
win_builder,
|
|
|
|
ctx_builder,
|
|
|
|
&events_loop,
|
2019-01-11 23:18:34 +00:00
|
|
|
).map_err(|err| Error::BackendError(Box::new(err)))?;
|
2019-01-02 21:25:01 +00:00
|
|
|
|
2019-01-07 21:10:31 +00:00
|
|
|
let tmp = Ok(Self {
|
2019-01-02 21:25:01 +00:00
|
|
|
events_loop,
|
2019-01-11 17:30:13 +00:00
|
|
|
renderer: Renderer::new(
|
|
|
|
device,
|
|
|
|
factory,
|
|
|
|
tgt_color_view,
|
|
|
|
tgt_depth_view,
|
|
|
|
)?,
|
2019-01-23 22:21:47 +00:00
|
|
|
window,
|
|
|
|
cursor_grabbed: false,
|
2019-01-07 21:10:31 +00:00
|
|
|
});
|
|
|
|
tmp
|
2019-01-02 21:25:01 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 21:10:31 +00:00
|
|
|
pub fn renderer(&self) -> &Renderer { &self.renderer }
|
|
|
|
pub fn renderer_mut(&mut self) -> &mut Renderer { &mut self.renderer }
|
2019-01-02 22:08:13 +00:00
|
|
|
|
2019-01-07 21:10:31 +00:00
|
|
|
pub fn fetch_events(&mut self) -> Vec<Event> {
|
2019-01-23 22:21:47 +00:00
|
|
|
// Copy data that is needed by the events closure to avoid lifetime errors
|
|
|
|
// TODO: Remove this if/when the compiler permits it
|
|
|
|
let cursor_grabbed = self.cursor_grabbed;
|
2019-01-23 22:39:31 +00:00
|
|
|
let renderer = &mut self.renderer;
|
|
|
|
let window = &mut self.window;
|
2019-01-23 22:21:47 +00:00
|
|
|
|
2019-01-07 21:10:31 +00:00
|
|
|
let mut events = vec![];
|
2019-01-02 21:25:01 +00:00
|
|
|
self.events_loop.poll_events(|event| match event {
|
2019-01-11 17:30:13 +00:00
|
|
|
glutin::Event::WindowEvent { event, .. } => match event {
|
|
|
|
glutin::WindowEvent::CloseRequested => events.push(Event::Close),
|
2019-01-23 22:39:31 +00:00
|
|
|
glutin::WindowEvent::Resized(glutin::dpi::LogicalSize { width, height }) => {
|
|
|
|
let (mut color_view, mut depth_view) = renderer.target_views_mut();
|
|
|
|
gfx_window_glutin::update_views(
|
|
|
|
&window,
|
|
|
|
&mut color_view,
|
|
|
|
&mut depth_view,
|
|
|
|
);
|
|
|
|
events.push(Event::Resize(Vec2::new(width as u32, height as u32)));
|
|
|
|
},
|
2019-01-11 23:18:34 +00:00
|
|
|
glutin::WindowEvent::ReceivedCharacter(c) => events.push(Event::Char(c)),
|
2019-01-23 22:21:47 +00:00
|
|
|
glutin::WindowEvent::KeyboardInput { input, .. } => match input.virtual_keycode {
|
|
|
|
Some(glutin::VirtualKeyCode::Escape) => events.push(if input.state == glutin::ElementState::Pressed {
|
|
|
|
Event::KeyDown(Key::ToggleCursor)
|
|
|
|
} else {
|
|
|
|
Event::KeyUp(Key::ToggleCursor)
|
|
|
|
}),
|
|
|
|
_ => {},
|
|
|
|
},
|
2019-01-02 21:25:01 +00:00
|
|
|
_ => {},
|
|
|
|
},
|
2019-01-12 13:56:34 +00:00
|
|
|
glutin::Event::DeviceEvent { event, .. } => match event {
|
2019-01-23 22:21:47 +00:00
|
|
|
glutin::DeviceEvent::MouseMotion { delta: (dx, dy), .. } if cursor_grabbed =>
|
2019-01-12 13:56:34 +00:00
|
|
|
events.push(Event::CursorPan(Vec2::new(dx as f32, dy as f32))),
|
2019-01-30 12:11:34 +00:00
|
|
|
glutin::DeviceEvent::MouseWheel {
|
|
|
|
delta: glutin::MouseScrollDelta::LineDelta(_x, y),
|
|
|
|
..
|
|
|
|
} if cursor_grabbed => events.push(Event::Zoom(y as f32)),
|
2019-01-12 13:56:34 +00:00
|
|
|
_ => {},
|
|
|
|
},
|
2019-01-02 21:25:01 +00:00
|
|
|
_ => {},
|
|
|
|
});
|
2019-01-07 21:10:31 +00:00
|
|
|
events
|
2019-01-02 21:25:01 +00:00
|
|
|
}
|
|
|
|
|
2019-01-12 01:14:58 +00:00
|
|
|
pub fn swap_buffers(&self) -> Result<(), Error> {
|
2019-01-11 17:30:13 +00:00
|
|
|
self.window.swap_buffers()
|
2019-01-11 23:18:34 +00:00
|
|
|
.map_err(|err| Error::BackendError(Box::new(err)))
|
2019-01-02 21:25:01 +00:00
|
|
|
}
|
2019-01-12 01:14:58 +00:00
|
|
|
|
2019-01-23 22:21:47 +00:00
|
|
|
pub fn is_cursor_grabbed(&self) -> bool {
|
|
|
|
self.cursor_grabbed
|
2019-01-12 01:14:58 +00:00
|
|
|
}
|
|
|
|
|
2019-01-23 22:21:47 +00:00
|
|
|
pub fn grab_cursor(&mut self, grab: bool) {
|
|
|
|
self.cursor_grabbed = grab;
|
|
|
|
self.window.hide_cursor(grab);
|
|
|
|
self.window.grab_cursor(grab)
|
|
|
|
.expect("Failed to grab/ungrab cursor");
|
2019-01-12 01:14:58 +00:00
|
|
|
}
|
2019-01-02 21:25:01 +00:00
|
|
|
}
|
|
|
|
|
2019-01-23 22:21:47 +00:00
|
|
|
/// Represents a key that the game recognises after keyboard mapping
|
|
|
|
pub enum Key {
|
|
|
|
ToggleCursor,
|
|
|
|
}
|
|
|
|
|
2019-01-12 01:14:58 +00:00
|
|
|
/// Represents an incoming event from the window
|
2019-01-02 21:25:01 +00:00
|
|
|
pub enum Event {
|
2019-01-12 01:14:58 +00:00
|
|
|
/// The window has been requested to close.
|
2019-01-02 21:25:01 +00:00
|
|
|
Close,
|
2019-01-23 22:39:31 +00:00
|
|
|
/// The window has been resized
|
|
|
|
Resize(Vec2<u32>),
|
2019-01-12 01:14:58 +00:00
|
|
|
/// A key has been typed that corresponds to a specific character.
|
2019-01-11 23:18:34 +00:00
|
|
|
Char(char),
|
2019-01-23 22:21:47 +00:00
|
|
|
/// The cursor has been panned across the screen while grabbed.
|
2019-01-12 01:14:58 +00:00
|
|
|
CursorPan(Vec2<f32>),
|
2019-01-30 12:11:34 +00:00
|
|
|
/// The camera has been requested to zoom.
|
|
|
|
Zoom(f32),
|
2019-01-23 22:21:47 +00:00
|
|
|
/// A key that the game recognises has been pressed down
|
|
|
|
KeyDown(Key),
|
|
|
|
/// A key that the game recognises has been released down
|
|
|
|
KeyUp(Key),
|
2019-01-02 21:25:01 +00:00
|
|
|
}
|