diff --git a/src/app.rs b/src/app.rs index 3403b3b..a2be00c 100644 --- a/src/app.rs +++ b/src/app.rs @@ -8,7 +8,7 @@ use wgpu::util::DeviceExt as _; use winit::platform::windows::{CornerPreference, WindowAttributesExtWindows as _}; use winit::{ application::ApplicationHandler, - dpi::LogicalSize, + dpi::{LogicalSize, PhysicalSize}, event::{ElementState, Event, WindowEvent}, event_loop::ActiveEventLoop, keyboard::Key, @@ -297,17 +297,8 @@ impl ApplicationHandler for App { match &event { WindowEvent::Resized(size) => { - window.surface_desc = wgpu::SurfaceConfiguration { - usage: wgpu::TextureUsages::RENDER_ATTACHMENT, - format: wgpu::TextureFormat::Bgra8UnormSrgb, - width: size.width, - height: size.height, - present_mode: wgpu::PresentMode::Fifo, - desired_maximum_frame_latency: 2, - alpha_mode: wgpu::CompositeAlphaMode::Auto, - view_formats: vec![wgpu::TextureFormat::Bgra8Unorm], - }; - + window.surface_desc.width = size.width; + window.surface_desc.height = size.height; window .surface .configure(&window.device, &window.surface_desc); @@ -345,9 +336,9 @@ impl ApplicationHandler for App { .prepare_frame(imgui.context.io_mut(), &window.window) .expect("Failed to prepare frame"); let ui = imgui.context.frame(); - let mut height = 0.0; + let mut menu_height = 0.0; ui.main_menu_bar(|| { - height = ui.window_size()[1]; + menu_height = ui.window_size()[1]; ui.menu("ROM", || { if ui.menu_item("Open ROM") { let rom = native_dialog::FileDialog::new() @@ -374,6 +365,27 @@ impl ApplicationHandler for App { self.client.send_command(EmulatorCommand::Reset); } }); + ui.menu("Video", || { + let current_dims = PhysicalSize::new( + window.surface_desc.width, + window.surface_desc.height, + ) + .to_logical(window.hidpi_factor); + for scale in 1..=4 { + let label = format!("x{scale}"); + let dims = LogicalSize::new(384 * scale, 224 * scale + 20); + let selected = dims == current_dims; + if ui.menu_item_config(label).selected(selected).build() { + if let Some(size) = window.window.request_inner_size(dims) { + window.surface_desc.width = size.width; + window.surface_desc.height = size.height; + window + .surface + .configure(&window.device, &window.surface_desc); + } + } + } + }); }); let mut encoder: wgpu::CommandEncoder = window @@ -403,13 +415,19 @@ impl ApplicationHandler for App { occlusion_query_set: None, }); + // Draw the game rpass.set_pipeline(&window.pipeline); - let hidpi = window.hidpi_factor as f32; - rpass.set_viewport(0.0, height * hidpi, 384.0 * hidpi, 224.0 * hidpi, 0.0, 1.0); + let window_width = window.surface_desc.width as f32; + let window_height = window.surface_desc.height as f32; + let menu_height = menu_height * window.hidpi_factor as f32; + let ((x, y), (width, height)) = + compute_game_bounds(window_width, window_height, menu_height); + rpass.set_viewport(x, y, width, height, 0.0, 1.0); rpass.set_bind_group(0, &window.bind_group, &[]); rpass.draw(0..6, 0..1); - rpass.set_viewport(0.0, 0.0, 384.0 * hidpi, 224.0 * hidpi, 0.0, 1.0); + // Draw the menu on top of the game + rpass.set_viewport(0.0, 0.0, window_width, window_height, 0.0, 1.0); imgui .renderer .render( @@ -473,6 +491,21 @@ impl ApplicationHandler for App { } } +fn compute_game_bounds( + window_width: f32, + window_height: f32, + menu_height: f32, +) -> ((f32, f32), (f32, f32)) { + let available_width = window_width; + let available_height = window_height - menu_height; + + let width = available_width.min(available_height * 384.0 / 224.0); + let height = available_height.min(available_width * 224.0 / 384.0); + let x = (available_width - width) / 2.0; + let y = menu_height + (available_height - height) / 2.0; + ((x, y), (width, height)) +} + #[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] #[repr(C)] struct Colors {