Merge branch 'new_keys' into 'master'

Added Keys for Fullscreen, Screenshots, and the Debug Window

See merge request veloren/veloren!151

Former-commit-id: 287a6b6582e3f5fb13a5d220f6648de5e4f50baa
This commit is contained in:
Joshua Barretto 2019-05-18 23:11:36 +00:00
commit 47502b8a7b
8 changed files with 142 additions and 8 deletions

1
.gitignore vendored
View File

@ -20,3 +20,4 @@ settings.toml
*.rar *.rar
*.log *.log
run.sh run.sh
screenshots

View File

@ -463,6 +463,10 @@ impl Hud {
pub fn handle_event(&mut self, event: WinEvent, global_state: &mut GlobalState) -> bool { pub fn handle_event(&mut self, event: WinEvent, global_state: &mut GlobalState) -> bool {
let cursor_grabbed = global_state.window.is_cursor_grabbed(); let cursor_grabbed = global_state.window.is_cursor_grabbed();
let handled = match event { let handled = match event {
WinEvent::SettingsChanged => {
self.settings = global_state.settings.clone();
false
}
WinEvent::Ui(event) => { WinEvent::Ui(event) => {
if (self.typing() && event.is_keyboard() && self.show.ui) if (self.typing() && event.is_keyboard() && self.show.ui)
|| !(cursor_grabbed && event.is_keyboard_or_mouse()) || !(cursor_grabbed && event.is_keyboard_or_mouse())
@ -534,6 +538,10 @@ impl Hud {
self.show.toggle_help(); self.show.toggle_help();
true true
} }
Key::ToggleDebug => {
self.show.debug = !self.show.debug;
true
}
_ => false, _ => false,
}, },
WinEvent::KeyDown(key) | WinEvent::KeyUp(key) => match key { WinEvent::KeyDown(key) | WinEvent::KeyUp(key) => match key {
@ -541,10 +549,6 @@ impl Hud {
_ => self.typing(), _ => self.typing(),
}, },
WinEvent::Char(_) => self.typing(), WinEvent::Char(_) => self.typing(),
WinEvent::SettingsChanged => {
self.settings = global_state.settings.clone();
true
}
_ => false, _ => false,
}; };
// Handle cursor grab. // Handle cursor grab.

View File

@ -42,6 +42,8 @@ pub enum RenderError {
CombinedError(gfx::CombinedError), CombinedError(gfx::CombinedError),
BufferCreationError(gfx::buffer::CreationError), BufferCreationError(gfx::buffer::CreationError),
IncludeError(glsl_include::Error), IncludeError(glsl_include::Error),
MappingError(gfx::mapping::Error),
CopyError(gfx::CopyError<[u16; 3], usize>),
} }
/// Used to represent a specific rendering configuration. /// Used to represent a specific rendering configuration.

View File

@ -306,6 +306,55 @@ impl Renderer {
texture.update(&mut self.encoder, offset, size, data) texture.update(&mut self.encoder, offset, size, data)
} }
/// Creates a download buffer, downloads the win_color_view, and converts to a image::DynamicImage.
pub fn create_screenshot(&mut self) -> Result<image::DynamicImage, RenderError> {
let (width, height) = self.get_resolution().into_tuple();
use gfx::{
format::{Formatted, SurfaceTyped},
memory::Typed,
};
type WinSurfaceData = <<WinColorFmt as Formatted>::Surface as SurfaceTyped>::DataType;
let mut download = self
.factory
.create_download_buffer::<WinSurfaceData>(width as usize * height as usize)
.map_err(|err| RenderError::BufferCreationError(err))?;
self.encoder
.copy_texture_to_buffer_raw(
self.win_color_view.raw().get_texture(),
None,
gfx::texture::RawImageInfo {
xoffset: 0,
yoffset: 0,
zoffset: 0,
width,
height,
depth: 0,
format: WinColorFmt::get_format(),
mipmap: 0,
},
download.raw(),
0,
)
.map_err(|err| RenderError::CopyError(err))?;
self.flush();
// Assumes that the format is Rgba8.
let raw_data = self
.factory
.read_mapping(&download)
.map_err(|err| RenderError::MappingError(err))?
.chunks_exact(width as usize)
.rev()
.flatten()
.flatten()
.map(|&e| e)
.collect::<Vec<_>>();
Ok(image::DynamicImage::ImageRgba8(
// Should not fail if the dimensions are correct.
image::ImageBuffer::from_raw(width as u32, height as u32, raw_data).unwrap(),
))
}
/// Queue the rendering of the provided skybox model in the upcoming frame. /// Queue the rendering of the provided skybox model in the upcoming frame.
pub fn render_skybox( pub fn render_skybox(
&mut self, &mut self,

View File

@ -35,6 +35,9 @@ pub struct ControlSettings {
pub settings: VirtualKeyCode, pub settings: VirtualKeyCode,
pub help: VirtualKeyCode, pub help: VirtualKeyCode,
pub toggle_interface: VirtualKeyCode, pub toggle_interface: VirtualKeyCode,
pub toggle_debug: VirtualKeyCode,
pub fullscreen: VirtualKeyCode,
pub screenshot: VirtualKeyCode,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
@ -71,6 +74,9 @@ impl Default for Settings {
settings: VirtualKeyCode::N, settings: VirtualKeyCode::N,
help: VirtualKeyCode::F1, help: VirtualKeyCode::F1,
toggle_interface: VirtualKeyCode::F2, toggle_interface: VirtualKeyCode::F2,
toggle_debug: VirtualKeyCode::F3,
fullscreen: VirtualKeyCode::F11,
screenshot: VirtualKeyCode::F4,
}, },
networking: NetworkingSettings { networking: NetworkingSettings {
username: "Username".to_string(), username: "Username".to_string(),

View File

@ -55,7 +55,7 @@ impl GraphicCache {
mut cacher: F, mut cacher: F,
) -> Option<Aabr<u16>> ) -> Option<Aabr<u16>>
where where
F: FnMut(Aabr<u16>, Vec<[u8; 4]>), F: FnMut(Aabr<u16>, &[[u8; 4]]),
{ {
match self match self
.rect_map .rect_map
@ -94,6 +94,7 @@ impl GraphicCache {
image::FilterType::Nearest, image::FilterType::Nearest,
) )
.to_rgba() .to_rgba()
// TODO: might be a better way to do this
.pixels() .pixels()
.map(|p| p.data) .map(|p| p.data)
.collect::<Vec<[u8; 4]>>(), .collect::<Vec<[u8; 4]>>(),
@ -103,7 +104,7 @@ impl GraphicCache {
}; };
// Draw to allocated area. // Draw to allocated area.
cacher(aabr, data); cacher(aabr, &data);
// Insert area into map for retrieval. // Insert area into map for retrieval.
self.rect_map self.rect_map

View File

@ -347,7 +347,7 @@ impl Ui {
|aabr, data| { |aabr, data| {
let offset = aabr.min.into_array(); let offset = aabr.min.into_array();
let size = aabr.size().into_array(); let size = aabr.size().into_array();
renderer.update_texture(cache_tex, offset, size, &data); renderer.update_texture(cache_tex, offset, size, data);
}, },
) { ) {
Some(aabr) => Aabr { Some(aabr) => Aabr {

View File

@ -11,6 +11,7 @@ pub struct Window {
renderer: Renderer, renderer: Renderer,
window: glutin::GlWindow, window: glutin::GlWindow,
cursor_grabbed: bool, cursor_grabbed: bool,
fullscreen: bool,
needs_refresh_resize: bool, needs_refresh_resize: bool,
key_map: HashMap<glutin::VirtualKeyCode, Key>, key_map: HashMap<glutin::VirtualKeyCode, Key>,
supplement_events: Vec<Event>, supplement_events: Vec<Event>,
@ -56,12 +57,16 @@ impl Window {
key_map.insert(settings.controls.settings, Key::Settings); key_map.insert(settings.controls.settings, Key::Settings);
key_map.insert(settings.controls.help, Key::Help); key_map.insert(settings.controls.help, Key::Help);
key_map.insert(settings.controls.toggle_interface, Key::ToggleInterface); key_map.insert(settings.controls.toggle_interface, Key::ToggleInterface);
key_map.insert(settings.controls.toggle_debug, Key::ToggleDebug);
key_map.insert(settings.controls.fullscreen, Key::Fullscreen);
key_map.insert(settings.controls.screenshot, Key::Screenshot);
let tmp = Ok(Self { let tmp = Ok(Self {
events_loop, events_loop,
renderer: Renderer::new(device, factory, win_color_view, win_depth_view)?, renderer: Renderer::new(device, factory, win_color_view, win_depth_view)?,
window, window,
cursor_grabbed: false, cursor_grabbed: false,
fullscreen: false,
needs_refresh_resize: false, needs_refresh_resize: false,
key_map, key_map,
supplement_events: vec![], supplement_events: vec![],
@ -91,6 +96,8 @@ impl Window {
let renderer = &mut self.renderer; let renderer = &mut self.renderer;
let window = &mut self.window; let window = &mut self.window;
let key_map = &self.key_map; let key_map = &self.key_map;
let mut toggle_fullscreen = false;
let mut take_screenshot = false;
self.events_loop.poll_events(|event| { self.events_loop.poll_events(|event| {
// Get events for ui. // Get events for ui.
@ -112,9 +119,19 @@ impl Window {
glutin::WindowEvent::KeyboardInput { input, .. } => match input.virtual_keycode glutin::WindowEvent::KeyboardInput { input, .. } => match input.virtual_keycode
{ {
Some(keycode) => match key_map.get(&keycode) { Some(keycode) => match key_map.get(&keycode) {
Some(Key::Fullscreen) => match input.state {
glutin::ElementState::Pressed => {
toggle_fullscreen = !toggle_fullscreen
}
_ => (),
},
Some(Key::Screenshot) => match input.state {
glutin::ElementState::Pressed => take_screenshot = true,
_ => {}
},
Some(&key) => events.push(match input.state { Some(&key) => events.push(match input.state {
glutin::ElementState::Pressed => Event::KeyDown(key), glutin::ElementState::Pressed => Event::KeyDown(key),
_ => Event::KeyUp(key), glutin::ElementState::Released => Event::KeyUp(key),
}), }),
_ => {} _ => {}
}, },
@ -137,6 +154,15 @@ impl Window {
_ => {} _ => {}
} }
}); });
if take_screenshot {
self.take_screenshot();
}
if toggle_fullscreen {
self.fullscreen(!self.is_fullscreen());
}
events events
} }
@ -156,6 +182,20 @@ impl Window {
let _ = self.window.grab_cursor(grab); let _ = self.window.grab_cursor(grab);
} }
pub fn is_fullscreen(&self) -> bool {
self.fullscreen
}
pub fn fullscreen(&mut self, fullscreen: bool) {
self.fullscreen = fullscreen;
if fullscreen {
self.window
.set_fullscreen(Some(self.window.get_current_monitor()));
} else {
self.window.set_fullscreen(None);
}
}
pub fn needs_refresh_resize(&mut self) { pub fn needs_refresh_resize(&mut self) {
self.needs_refresh_resize = true; self.needs_refresh_resize = true;
} }
@ -172,6 +212,34 @@ impl Window {
pub fn send_supplement_event(&mut self, event: Event) { pub fn send_supplement_event(&mut self, event: Event) {
self.supplement_events.push(event) self.supplement_events.push(event)
} }
pub fn take_screenshot(&mut self) {
match self.renderer.create_screenshot() {
Ok(img) => {
std::thread::spawn(move || {
use std::{path::PathBuf, time::SystemTime};
// Check if folder exists and create it if it does not
let mut path = std::path::PathBuf::from("./screenshots");
if !path.exists() {
if let Err(err) = std::fs::create_dir(&path) {
log::error!("Coudn't create folder for screenshot: {:?}", err);
}
}
path.push(format!(
"screenshot_{}.png",
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.map(|d| d.as_millis())
.unwrap_or(0)
));
if let Err(err) = img.save(&path) {
log::error!("Coudn't save screenshot: {:?}", err);
}
});
}
Err(err) => log::error!("Coudn't create screenshot due to renderer error: {:?}", err),
}
}
} }
/// Represents a key that the game recognises after keyboard mapping. /// Represents a key that the game recognises after keyboard mapping.
@ -195,6 +263,9 @@ pub enum Key {
Settings, Settings,
ToggleInterface, ToggleInterface,
Help, Help,
ToggleDebug,
Fullscreen,
Screenshot,
} }
/// Represents an incoming event from the window. /// Represents an incoming event from the window.