screenshots!

This commit is contained in:
Alex Janka 2023-10-10 14:15:40 +11:00
parent a74d9e4d1a
commit e53dff0a30
4 changed files with 82 additions and 3 deletions

5
Cargo.lock generated
View file

@ -509,8 +509,10 @@ checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"serde",
"wasm-bindgen",
"windows-targets 0.48.5",
]
@ -1247,12 +1249,15 @@ dependencies = [
name = "gb-emu"
version = "0.4.0"
dependencies = [
"bytemuck",
"chrono",
"clap",
"cpal",
"ctrlc",
"futures",
"gb-emu-lib",
"gilrs",
"image",
"nokhwa",
"raw-window-handle",
"send_wrapper",

View file

@ -31,3 +31,6 @@ winit = "0.28"
winit_input_helper = "0.14"
raw-window-handle = { version = "0.5", optional = true }
serde = { version = "1.0", features = ["derive"] }
image = { version = "0.24", default-features = false, features = ["png"] }
bytemuck = "1.14"
chrono = "0.4"

View file

@ -16,7 +16,7 @@ use gilrs::Gilrs;
use serde::{Deserialize, Serialize};
use std::{
path::PathBuf,
sync::mpsc::channel,
sync::{mpsc::channel, OnceLock},
time::{Duration, Instant},
};
use window::{WindowManager, WindowRenderer};
@ -81,13 +81,31 @@ struct Args {
#[serde(default)]
pub struct StandaloneConfig {
scale_factor: usize,
group_screenshots_by_rom: bool,
}
impl Default for StandaloneConfig {
fn default() -> Self {
Self { scale_factor: 3 }
Self {
scale_factor: 3,
group_screenshots_by_rom: true,
}
}
}
#[allow(dead_code)]
struct Configs {
standalone_config: StandaloneConfig,
emu_config: gb_emu_lib::config::Config,
config_dir: PathBuf,
rom_title: String,
}
static CONFIGS: OnceLock<Configs> = OnceLock::new();
fn access_config<'a>() -> &'a Configs {
CONFIGS.get().expect("accessed config before it was set!")
}
fn main() {
let args = Args::parse();
@ -168,6 +186,13 @@ fn run(args: Args) -> ! {
None
};
CONFIGS.get_or_init(|| Configs {
standalone_config,
emu_config: config.clone(),
config_dir: config_manager.dir(),
rom_title: rom.get_title().to_owned(),
});
let options =
EmulatorOptions::new_with_config(config, config_manager.dir(), window, rom, output)
.with_serial_target(if args.ascii {

View file

@ -13,6 +13,7 @@ use gilrs::{
ff::{BaseEffect, BaseEffectType, EffectBuilder, Replay, Ticks},
Button, Gilrs,
};
use image::ImageBuffer;
#[cfg(feature = "vulkan")]
use raw_window_handle::HasRawDisplayHandle;
use winit::{
@ -24,6 +25,8 @@ use winit::{
};
use winit_input_helper::WinitInputHelper;
use crate::access_config;
pub struct WindowInfo {
id: WindowId,
data: Arc<WindowData>,
@ -33,6 +36,7 @@ struct WindowData {
renderer: Mutex<RendererBackend>,
window: Window,
rendered_size: RwLock<(u32, u32)>,
last_buf: Mutex<Vec<[u8; 4]>>,
}
pub struct WindowManager {
@ -129,7 +133,44 @@ impl WindowManagerData {
control_flow.set_wait();
if let Ok(mut i) = self.input.lock() {
i.update(&event);
if i.update(&event) && i.key_pressed(VirtualKeyCode::Space) {
self.windows.iter().for_each(|(_id, window)| {
if let Ok(buf) = window.last_buf.lock() {
if let Ok(size) = window.rendered_size.read() {
let image = ImageBuffer::<image::Rgba<u8>, _>::from_raw(
size.0,
size.1,
bytemuck::cast_slice(buf.as_ref()),
)
.unwrap();
let configs = access_config();
let screenshot_dir =
if configs.standalone_config.group_screenshots_by_rom {
configs
.config_dir
.join(format!("screenshots/{}", configs.rom_title))
} else {
configs.config_dir.clone()
};
std::fs::create_dir_all(&screenshot_dir)
.expect("could not create screenshot directory!");
let screenshot_path = screenshot_dir.join(format!(
"{} - {}.png",
chrono::DateTime::<chrono::Local>::from(
std::time::SystemTime::now()
)
.to_rfc3339(),
configs.rom_title,
));
image
.save(screenshot_path)
.expect("Could not save screenshot!");
}
}
});
}
}
match event {
@ -218,6 +259,7 @@ impl WindowRenderer {
renderer,
window,
rendered_size: RwLock::new((1, 1)),
last_buf: Mutex::new(Vec::new()),
});
let info = WindowInfo {
@ -277,6 +319,10 @@ impl Renderer<[u8; 4]> for WindowRenderer {
data.new_frame(buffer);
}
self.data.window.request_redraw();
if let Ok(mut last_buf) = self.data.last_buf.lock() {
last_buf.resize(buffer.len(), [0; 4]);
last_buf.copy_from_slice(buffer);
}
}
fn set_title(&mut self, title: String) {