From 873037f9f1716835f95f720a27df063ee349d6d4 Mon Sep 17 00:00:00 2001 From: lifning <> Date: Tue, 19 Oct 2021 00:06:43 -0700 Subject: [PATCH] switch between gui/menu modes with esc, support drag-and-drop rom changing --- src/main.rs | 97 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 19 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9f58ca9..75604c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,11 +5,16 @@ use std::ffi::CStr; use std::path::PathBuf; use std::pin::Pin; -use sdl2::render::{WindowCanvas, BlendMode}; -use sdl2::image::ImageRWops; -use sdl2::surface::Surface; -use sdl2::pixels::{Color, PixelFormatEnum}; -use sdl2::rect::Point; +use sdl2::{ + EventPump, + event::Event, + image::ImageRWops, + keyboard::Keycode, + pixels::{Color, PixelFormatEnum}, + rect::Point, + render::{WindowCanvas, BlendMode}, + surface::Surface, +}; use rand::{SeedableRng, Rng}; use rand_xoshiro::Xoshiro128Plus; @@ -38,6 +43,20 @@ struct Opt { system: Option, } +enum GuiState { + Menus, + Game +} + +impl GuiState { + fn toggle(&mut self) { + match self { + GuiState::Menus => *self = GuiState::Game, + GuiState::Game => *self = GuiState::Menus, + } + } +} + struct Zretro { emu: Pin>, canvas: WindowCanvas, @@ -45,6 +64,8 @@ struct Zretro { rng: Xoshiro128Plus, ui_bg: Option>, snowflakes: Vec, + mode: GuiState, + event_pump: EventPump, } const FONT_PNG: &'static [u8] = include_bytes!("lifont.png"); @@ -53,7 +74,7 @@ impl Zretro { fn new(opt: Opt) -> Result { 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 title = format!( "zretro - {}", @@ -69,6 +90,8 @@ impl Zretro { .build()?; let canvas = window.into_canvas().build()?; + let event_pump = sdl_context.event_pump()?; + let sdl2surf_comp = Sdl2SurfaceComponent::new(emu.libretro_core())?; emu.register_component(sdl2surf_comp)?; @@ -86,7 +109,7 @@ impl Zretro { })?; 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 font_shortlived = rwops.load_png()?; @@ -114,6 +137,8 @@ impl Zretro { rng, ui_bg: Some(ui_bg), snowflakes, + mode: GuiState::Menus, + event_pump, }) } @@ -147,21 +172,55 @@ impl Zretro { let font_tx = tc.create_texture_from_surface(&self.font)?; let mut font_rect = self.font.rect(); font_rect.set_height(64); - while let ControlFlow::Continue = self.emu.run() { - self.update_snow()?; + 'outer: loop { + 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 surface = surfcomp.surface(); - - 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); - + let emu_surf_ref = surfcomp.surface(); + let emu_tx = tc.create_texture_from_surface(emu_surf_ref)?; self.canvas.clear(); 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(); } Ok(())