switch between gui/menu modes with esc, support drag-and-drop rom changing

This commit is contained in:
lifning 2021-10-19 00:06:43 -07:00
parent 5c0dd5558e
commit 873037f9f1
1 changed files with 78 additions and 19 deletions

View File

@ -5,11 +5,16 @@ use std::ffi::CStr;
use std::path::PathBuf; use std::path::PathBuf;
use std::pin::Pin; use std::pin::Pin;
use sdl2::render::{WindowCanvas, BlendMode}; use sdl2::{
use sdl2::image::ImageRWops; EventPump,
use sdl2::surface::Surface; event::Event,
use sdl2::pixels::{Color, PixelFormatEnum}; image::ImageRWops,
use sdl2::rect::Point; keyboard::Keycode,
pixels::{Color, PixelFormatEnum},
rect::Point,
render::{WindowCanvas, BlendMode},
surface::Surface,
};
use rand::{SeedableRng, Rng}; use rand::{SeedableRng, Rng};
use rand_xoshiro::Xoshiro128Plus; use rand_xoshiro::Xoshiro128Plus;
@ -38,6 +43,20 @@ struct Opt {
system: Option<PathBuf>, system: Option<PathBuf>,
} }
enum GuiState {
Menus,
Game
}
impl GuiState {
fn toggle(&mut self) {
match self {
GuiState::Menus => *self = GuiState::Game,
GuiState::Game => *self = GuiState::Menus,
}
}
}
struct Zretro { struct Zretro {
emu: Pin<Box<RetroComponentBase>>, emu: Pin<Box<RetroComponentBase>>,
canvas: WindowCanvas, canvas: WindowCanvas,
@ -45,6 +64,8 @@ struct Zretro {
rng: Xoshiro128Plus, rng: Xoshiro128Plus,
ui_bg: Option<Surface<'static>>, ui_bg: Option<Surface<'static>>,
snowflakes: Vec<Point>, snowflakes: Vec<Point>,
mode: GuiState,
event_pump: EventPump,
} }
const FONT_PNG: &'static [u8] = include_bytes!("lifont.png"); const FONT_PNG: &'static [u8] = include_bytes!("lifont.png");
@ -53,7 +74,7 @@ impl Zretro {
fn new(opt: Opt) -> Result<Self> { fn new(opt: Opt) -> Result<Self> {
let mut emu = RetroComponentBase::new(&opt.core); let mut emu = RetroComponentBase::new(&opt.core);
let geometry = emu.libretro_core().get_system_av_info().geometry; let SystemAvInfo { geometry, .. } = emu.libretro_core().get_system_av_info();
let sys_info = emu.libretro_core().get_system_info(); let sys_info = emu.libretro_core().get_system_info();
let title = format!( let title = format!(
"zretro - {}", "zretro - {}",
@ -69,6 +90,8 @@ impl Zretro {
.build()?; .build()?;
let canvas = window.into_canvas().build()?; let canvas = window.into_canvas().build()?;
let event_pump = sdl_context.event_pump()?;
let sdl2surf_comp = Sdl2SurfaceComponent::new(emu.libretro_core())?; let sdl2surf_comp = Sdl2SurfaceComponent::new(emu.libretro_core())?;
emu.register_component(sdl2surf_comp)?; emu.register_component(sdl2surf_comp)?;
@ -86,7 +109,7 @@ impl Zretro {
})?; })?;
emu.init().unwrap(); emu.init().unwrap();
emu.load_game(&opt.rom).unwrap(); emu.load_game(&opt.rom).unwrap(); // TODO: optional via CLI positional arg, menu-browsable
let rwops = sdl2::rwops::RWops::from_bytes(FONT_PNG)?; let rwops = sdl2::rwops::RWops::from_bytes(FONT_PNG)?;
let font_shortlived = rwops.load_png()?; let font_shortlived = rwops.load_png()?;
@ -114,6 +137,8 @@ impl Zretro {
rng, rng,
ui_bg: Some(ui_bg), ui_bg: Some(ui_bg),
snowflakes, snowflakes,
mode: GuiState::Menus,
event_pump,
}) })
} }
@ -147,21 +172,55 @@ impl Zretro {
let font_tx = tc.create_texture_from_surface(&self.font)?; let font_tx = tc.create_texture_from_surface(&self.font)?;
let mut font_rect = self.font.rect(); let mut font_rect = self.font.rect();
font_rect.set_height(64); font_rect.set_height(64);
while let ControlFlow::Continue = self.emu.run() { 'outer: loop {
self.update_snow()?; for event in self.event_pump.poll_iter() {
match event {
Event::Quit { .. } => break 'outer,
Event::KeyDown { keycode: Some(keycode), .. } => {
match keycode {
Keycode::Escape => {
self.mode.toggle();
let audio: &SimpleSdl2AudioComponent = self.emu.component_ref()?;
match self.mode {
GuiState::Menus => audio.silence_buffer(),
GuiState::Game => {} //audio.resume(),
}
},
_ => {}
}
}
Event::KeyUp { .. } => {}
Event::DropFile { filename, .. } => {
self.emu.libretro_core().unload_game();
self.emu.load_game(filename)?;
}
_ => {}
}
}
if let GuiState::Game = self.mode {
if let ControlFlow::Break = self.emu.run() {
break;
}
} else {
let delay: &mut SleepFramerateLimitComponent = self.emu.component_mut()?;
delay.do_sleep();
}
let surfcomp: &Sdl2SurfaceComponent = self.emu.component_ref()?; let surfcomp: &Sdl2SurfaceComponent = self.emu.component_ref()?;
let surface = surfcomp.surface(); let emu_surf_ref = surfcomp.surface();
let emu_tx = tc.create_texture_from_surface(emu_surf_ref)?;
let emu_tx = tc.create_texture_from_surface(surface)?;
let ui_bg_surf_ref = self.ui_bg.as_ref().ok_or("no bg?")?;
let mut ui_tx = tc.create_texture_from_surface(ui_bg_surf_ref)?;
ui_tx.set_blend_mode(BlendMode::Blend);
self.canvas.clear(); self.canvas.clear();
self.canvas.copy(&emu_tx, None, None)?; self.canvas.copy(&emu_tx, None, None)?;
self.canvas.copy(&ui_tx, None, None)?;
self.canvas.copy(&font_tx, font_rect, font_rect)?; if let GuiState::Menus = self.mode {
self.update_snow()?;
let ui_bg_surf_ref = self.ui_bg.as_ref().ok_or("no bg?")?;
let mut ui_tx = tc.create_texture_from_surface(ui_bg_surf_ref)?;
ui_tx.set_blend_mode(BlendMode::Blend);
self.canvas.copy(&ui_tx, None, None)?;
self.canvas.copy(&font_tx, font_rect, font_rect)?;
}
self.canvas.present(); self.canvas.present();
} }
Ok(()) Ok(())