mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add screenshot, fullscreen, & debug keys
Former-commit-id: 9358575794b71535905c5133eb6764284c35fb34
This commit is contained in:
parent
9e9e8be196
commit
7855dfe52f
1
.gitignore
vendored
1
.gitignore
vendored
@ -20,3 +20,4 @@ settings.toml
|
||||
*.rar
|
||||
*.log
|
||||
run.sh
|
||||
screenshots
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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<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))?
|
||||
.iter()
|
||||
.rev()
|
||||
.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.
|
||||
pub fn render_skybox(
|
||||
&mut self,
|
||||
|
@ -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(),
|
||||
|
@ -55,7 +55,7 @@ impl GraphicCache {
|
||||
mut cacher: F,
|
||||
) -> Option<Aabr<u16>>
|
||||
where
|
||||
F: FnMut(Aabr<u16>, Vec<[u8; 4]>),
|
||||
F: FnMut(Aabr<u16>, &[[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::<Vec<[u8; 4]>>(),
|
||||
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -11,6 +11,7 @@ pub struct Window {
|
||||
renderer: Renderer,
|
||||
window: glutin::GlWindow,
|
||||
cursor_grabbed: bool,
|
||||
fullscreen: bool,
|
||||
needs_refresh_resize: bool,
|
||||
key_map: HashMap<glutin::VirtualKeyCode, Key>,
|
||||
supplement_events: Vec<Event>,
|
||||
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user