screenshots!
This commit is contained in:
parent
a74d9e4d1a
commit
e53dff0a30
4 changed files with 82 additions and 3 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,12 +81,30 @@ 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() {
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue