From 7855dfe52fb56a3f0bd43aac66cb3f35f4b3c2aa Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 18 May 2019 17:16:35 -0400 Subject: [PATCH] Add screenshot, fullscreen, & debug keys Former-commit-id: 9358575794b71535905c5133eb6764284c35fb34 --- .gitignore | 1 + voxygen/src/hud/mod.rs | 4 ++ voxygen/src/render/mod.rs | 2 + voxygen/src/render/renderer.rs | 48 ++++++++++++++++++++ voxygen/src/settings.rs | 6 +++ voxygen/src/ui/graphic/graphic.rs | 5 ++- voxygen/src/ui/mod.rs | 2 +- voxygen/src/window.rs | 73 ++++++++++++++++++++++++++++++- 8 files changed, 137 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index abc6feeddb..23ff1bf194 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ settings.toml *.rar *.log run.sh +screenshots \ No newline at end of file diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 70a9416e2c..32411f7891 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -538,6 +538,10 @@ impl Hud { self.show.toggle_help(); true } + Key::ToggleDebug => { + self.show.debug = !self.show.debug; + true + } _ => false, }, WinEvent::KeyDown(key) | WinEvent::KeyUp(key) => match key { diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index fd42f5461e..9159b8d0aa 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -42,6 +42,8 @@ pub enum RenderError { CombinedError(gfx::CombinedError), BufferCreationError(gfx::buffer::CreationError), IncludeError(glsl_include::Error), + MappingError(gfx::mapping::Error), + CopyError(gfx::CopyError<[u16; 3], usize>), } /// Used to represent a specific rendering configuration. diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 256266d23f..02b4a178c8 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -306,6 +306,54 @@ impl Renderer { 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 { + let (width, height) = self.get_resolution().into_tuple(); + use gfx::{ + format::{Formatted, SurfaceTyped}, + memory::Typed, + }; + type WinSurfaceData = <::Surface as SurfaceTyped>::DataType; + let mut download = self + .factory + .create_download_buffer::(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))? + .iter() + .rev() + .flatten() + .map(|&e| e) + .collect::>(); + 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. pub fn render_skybox( &mut self, diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 3671bce90f..0fab421cd9 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -35,6 +35,9 @@ pub struct ControlSettings { pub settings: VirtualKeyCode, pub help: VirtualKeyCode, pub toggle_interface: VirtualKeyCode, + pub toggle_debug: VirtualKeyCode, + pub fullscreen: VirtualKeyCode, + pub screenshot: VirtualKeyCode, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -71,6 +74,9 @@ impl Default for Settings { settings: VirtualKeyCode::N, help: VirtualKeyCode::F1, toggle_interface: VirtualKeyCode::F2, + toggle_debug: VirtualKeyCode::F3, + fullscreen: VirtualKeyCode::F11, + screenshot: VirtualKeyCode::F4, }, networking: NetworkingSettings { username: "Username".to_string(), diff --git a/voxygen/src/ui/graphic/graphic.rs b/voxygen/src/ui/graphic/graphic.rs index cbc004cf6d..03dac64033 100644 --- a/voxygen/src/ui/graphic/graphic.rs +++ b/voxygen/src/ui/graphic/graphic.rs @@ -55,7 +55,7 @@ impl GraphicCache { mut cacher: F, ) -> Option> where - F: FnMut(Aabr, Vec<[u8; 4]>), + F: FnMut(Aabr, &[[u8; 4]]), { match self .rect_map @@ -94,6 +94,7 @@ impl GraphicCache { image::FilterType::Nearest, ) .to_rgba() + // TODO: might be a better way to do this .pixels() .map(|p| p.data) .collect::>(), @@ -103,7 +104,7 @@ impl GraphicCache { }; // Draw to allocated area. - cacher(aabr, data); + cacher(aabr, &data); // Insert area into map for retrieval. self.rect_map diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 40452bed1e..0ad8129663 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -347,7 +347,7 @@ impl Ui { |aabr, data| { let offset = aabr.min.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 { diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index d91c7d8bdc..135751109b 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -11,6 +11,7 @@ pub struct Window { renderer: Renderer, window: glutin::GlWindow, cursor_grabbed: bool, + fullscreen: bool, needs_refresh_resize: bool, key_map: HashMap, supplement_events: Vec, @@ -56,12 +57,16 @@ impl Window { key_map.insert(settings.controls.settings, Key::Settings); key_map.insert(settings.controls.help, Key::Help); 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 { events_loop, renderer: Renderer::new(device, factory, win_color_view, win_depth_view)?, window, cursor_grabbed: false, + fullscreen: false, needs_refresh_resize: false, key_map, supplement_events: vec![], @@ -91,6 +96,8 @@ impl Window { let renderer = &mut self.renderer; let window = &mut self.window; let key_map = &self.key_map; + let mut toggle_fullscreen = false; + let mut take_screenshot = false; self.events_loop.poll_events(|event| { // Get events for ui. @@ -112,9 +119,19 @@ impl Window { glutin::WindowEvent::KeyboardInput { input, .. } => match input.virtual_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 { 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 } @@ -156,6 +182,20 @@ impl Window { 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) { self.needs_refresh_resize = true; } @@ -172,6 +212,34 @@ impl Window { pub fn send_supplement_event(&mut self, event: 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. @@ -195,6 +263,9 @@ pub enum Key { Settings, ToggleInterface, Help, + ToggleDebug, + Fullscreen, + Screenshot, } /// Represents an incoming event from the window.