lemur/src/window/game.rs

181 lines
6.4 KiB
Rust
Raw Normal View History

2024-11-28 15:27:18 +00:00
use crate::{
app::UserEvent,
emulator::{EmulatorClient, EmulatorCommand, SimId},
2024-11-26 05:38:03 +00:00
};
use egui::{
menu, Button, CentralPanel, Color32, Context, Response, TopBottomPanel, Ui, ViewportBuilder,
ViewportCommand, ViewportId, WidgetText,
};
2024-11-28 15:27:18 +00:00
use winit::event_loop::EventLoopProxy;
2024-11-26 05:38:03 +00:00
use super::{game_screen::GameScreen, AppWindow};
pub struct GameWindow {
client: EmulatorClient,
2024-11-28 15:27:18 +00:00
proxy: EventLoopProxy<UserEvent>,
2024-11-26 05:38:03 +00:00
sim_id: SimId,
screen: Option<GameScreen>,
}
impl GameWindow {
2024-11-28 15:27:18 +00:00
pub fn new(client: EmulatorClient, proxy: EventLoopProxy<UserEvent>, sim_id: SimId) -> Self {
2024-11-26 05:38:03 +00:00
Self {
client,
2024-11-28 15:27:18 +00:00
proxy,
2024-11-26 05:38:03 +00:00
sim_id,
screen: None,
}
}
fn show_menu(&mut self, ctx: &Context, ui: &mut Ui) {
ui.menu_button("ROM", |ui| {
if ui.button("Open ROM").clicked() {
let rom = rfd::FileDialog::new()
.add_filter("Virtual Boy ROMs", &["vb", "vbrom"])
.pick_file();
if let Some(path) = rom {
self.client
.send_command(EmulatorCommand::LoadGame(SimId::Player1, path));
}
ui.close_menu();
}
if ui.button("Quit").clicked() {
ctx.send_viewport_cmd(ViewportCommand::Close);
}
});
ui.menu_button("Emulation", |ui| {
let has_game = self.client.has_game(self.sim_id);
if self.client.is_running(self.sim_id) {
if ui.add_enabled(has_game, Button::new("Pause")).clicked() {
self.client.send_command(EmulatorCommand::Pause);
ui.close_menu();
}
} else if ui.add_enabled(has_game, Button::new("Resume")).clicked() {
self.client.send_command(EmulatorCommand::Resume);
ui.close_menu();
}
if ui.add_enabled(has_game, Button::new("Reset")).clicked() {
self.client
.send_command(EmulatorCommand::Reset(self.sim_id));
ui.close_menu();
}
});
ui.menu_button("Video", |ui| {
let current_dims = ctx.input(|i| i.viewport().inner_rect.unwrap());
let current_dims = current_dims.max - current_dims.min;
for scale in 1..=4 {
let label = format!("x{scale}");
let scale = scale as f32;
let dims = (384.0 * scale, 224.0 * scale + 20.0).into();
if ui
.selectable_button((current_dims - dims).length() < 1.0, label)
.clicked()
{
ctx.send_viewport_cmd(ViewportCommand::InnerSize(dims));
ui.close_menu();
}
}
});
ui.menu_button("Audio", |ui| {
let p1_enabled = self.client.is_audio_enabled(SimId::Player1);
let p2_enabled = self.client.is_audio_enabled(SimId::Player2);
if ui.selectable_button(p1_enabled, "Player 1").clicked() {
self.client
.send_command(EmulatorCommand::SetAudioEnabled(!p1_enabled, p2_enabled));
ui.close_menu();
}
if ui.selectable_button(p2_enabled, "Player 2").clicked() {
self.client
.send_command(EmulatorCommand::SetAudioEnabled(p1_enabled, !p2_enabled));
ui.close_menu();
}
});
ui.menu_button("Input", |ui| {
if ui.button("Bind Inputs").clicked() {
2024-11-28 15:27:18 +00:00
self.proxy.send_event(UserEvent::OpenInput).unwrap();
2024-11-26 05:38:03 +00:00
ui.close_menu();
}
});
ui.menu_button("Multiplayer", |ui| {
if self.sim_id == SimId::Player1
&& !self.client.has_player_2()
&& ui.button("Open Player 2").clicked()
{
self.client
.send_command(EmulatorCommand::StartSecondSim(None));
2024-11-28 15:27:18 +00:00
self.proxy.send_event(UserEvent::OpenPlayer2).unwrap();
2024-11-26 05:38:03 +00:00
ui.close_menu();
}
if self.client.has_player_2() {
let linked = self.client.are_sims_linked();
if linked && ui.button("Unlink").clicked() {
self.client.send_command(EmulatorCommand::Unlink);
ui.close_menu();
}
if !linked && ui.button("Link").clicked() {
self.client.send_command(EmulatorCommand::Link);
ui.close_menu();
}
}
});
}
}
impl AppWindow for GameWindow {
fn viewport_id(&self) -> ViewportId {
match self.sim_id {
SimId::Player1 => ViewportId::ROOT,
SimId::Player2 => ViewportId::from_hash_of("Player2"),
}
}
fn initial_viewport(&self) -> ViewportBuilder {
ViewportBuilder::default()
.with_title("Shrooms VB")
.with_inner_size((384.0, 244.0))
}
fn show(&mut self, ctx: &Context) {
TopBottomPanel::top("menubar")
.exact_height(20.0)
.show(ctx, |ui| {
menu::bar(ui, |ui| {
self.show_menu(ctx, ui);
});
});
CentralPanel::default().show(ctx, |ui| {
if let Some(screen) = self.screen.as_ref() {
ui.add(screen);
}
});
}
2024-11-28 15:27:18 +00:00
fn on_init(&mut self, render_state: &egui_wgpu::RenderState) {
let (screen, sink) = GameScreen::init(render_state);
self.client
.send_command(EmulatorCommand::SetRenderer(self.sim_id, sink));
self.screen = Some(screen)
}
fn on_destroy(&mut self) {
if self.sim_id == SimId::Player2 {
self.client.send_command(EmulatorCommand::StopSecondSim);
}
}
2024-11-26 05:38:03 +00:00
}
trait UiExt {
fn selectable_button(&mut self, selected: bool, text: impl Into<WidgetText>) -> Response;
}
impl UiExt for Ui {
fn selectable_button(&mut self, selected: bool, text: impl Into<WidgetText>) -> Response {
self.style_mut().visuals.widgets.inactive.bg_fill = Color32::TRANSPARENT;
self.style_mut().visuals.widgets.hovered.bg_fill = Color32::TRANSPARENT;
self.style_mut().visuals.widgets.active.bg_fill = Color32::TRANSPARENT;
let mut selected = selected;
self.checkbox(&mut selected, text)
}
}