Support resizing the window
This commit is contained in:
		
							parent
							
								
									593475960d
								
							
						
					
					
						commit
						75fa3be25c
					
				
							
								
								
									
										67
									
								
								src/app.rs
								
								
								
								
							
							
						
						
									
										67
									
								
								src/app.rs
								
								
								
								
							| 
						 | 
					@ -8,7 +8,7 @@ use wgpu::util::DeviceExt as _;
 | 
				
			||||||
use winit::platform::windows::{CornerPreference, WindowAttributesExtWindows as _};
 | 
					use winit::platform::windows::{CornerPreference, WindowAttributesExtWindows as _};
 | 
				
			||||||
use winit::{
 | 
					use winit::{
 | 
				
			||||||
    application::ApplicationHandler,
 | 
					    application::ApplicationHandler,
 | 
				
			||||||
    dpi::LogicalSize,
 | 
					    dpi::{LogicalSize, PhysicalSize},
 | 
				
			||||||
    event::{ElementState, Event, WindowEvent},
 | 
					    event::{ElementState, Event, WindowEvent},
 | 
				
			||||||
    event_loop::ActiveEventLoop,
 | 
					    event_loop::ActiveEventLoop,
 | 
				
			||||||
    keyboard::Key,
 | 
					    keyboard::Key,
 | 
				
			||||||
| 
						 | 
					@ -297,17 +297,8 @@ impl ApplicationHandler for App {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match &event {
 | 
					        match &event {
 | 
				
			||||||
            WindowEvent::Resized(size) => {
 | 
					            WindowEvent::Resized(size) => {
 | 
				
			||||||
                window.surface_desc = wgpu::SurfaceConfiguration {
 | 
					                window.surface_desc.width = size.width;
 | 
				
			||||||
                    usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
 | 
					                window.surface_desc.height = size.height;
 | 
				
			||||||
                    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
 | 
					                window
 | 
				
			||||||
                    .surface
 | 
					                    .surface
 | 
				
			||||||
                    .configure(&window.device, &window.surface_desc);
 | 
					                    .configure(&window.device, &window.surface_desc);
 | 
				
			||||||
| 
						 | 
					@ -345,9 +336,9 @@ impl ApplicationHandler for App {
 | 
				
			||||||
                    .prepare_frame(imgui.context.io_mut(), &window.window)
 | 
					                    .prepare_frame(imgui.context.io_mut(), &window.window)
 | 
				
			||||||
                    .expect("Failed to prepare frame");
 | 
					                    .expect("Failed to prepare frame");
 | 
				
			||||||
                let ui = imgui.context.frame();
 | 
					                let ui = imgui.context.frame();
 | 
				
			||||||
                let mut height = 0.0;
 | 
					                let mut menu_height = 0.0;
 | 
				
			||||||
                ui.main_menu_bar(|| {
 | 
					                ui.main_menu_bar(|| {
 | 
				
			||||||
                    height = ui.window_size()[1];
 | 
					                    menu_height = ui.window_size()[1];
 | 
				
			||||||
                    ui.menu("ROM", || {
 | 
					                    ui.menu("ROM", || {
 | 
				
			||||||
                        if ui.menu_item("Open ROM") {
 | 
					                        if ui.menu_item("Open ROM") {
 | 
				
			||||||
                            let rom = native_dialog::FileDialog::new()
 | 
					                            let rom = native_dialog::FileDialog::new()
 | 
				
			||||||
| 
						 | 
					@ -374,6 +365,27 @@ impl ApplicationHandler for App {
 | 
				
			||||||
                            self.client.send_command(EmulatorCommand::Reset);
 | 
					                            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
 | 
					                let mut encoder: wgpu::CommandEncoder = window
 | 
				
			||||||
| 
						 | 
					@ -403,13 +415,19 @@ impl ApplicationHandler for App {
 | 
				
			||||||
                    occlusion_query_set: None,
 | 
					                    occlusion_query_set: None,
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Draw the game
 | 
				
			||||||
                rpass.set_pipeline(&window.pipeline);
 | 
					                rpass.set_pipeline(&window.pipeline);
 | 
				
			||||||
                let hidpi = window.hidpi_factor as f32;
 | 
					                let window_width = window.surface_desc.width as f32;
 | 
				
			||||||
                rpass.set_viewport(0.0, height * hidpi, 384.0 * hidpi, 224.0 * hidpi, 0.0, 1.0);
 | 
					                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.set_bind_group(0, &window.bind_group, &[]);
 | 
				
			||||||
                rpass.draw(0..6, 0..1);
 | 
					                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
 | 
					                imgui
 | 
				
			||||||
                    .renderer
 | 
					                    .renderer
 | 
				
			||||||
                    .render(
 | 
					                    .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)]
 | 
					#[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
 | 
				
			||||||
#[repr(C)]
 | 
					#[repr(C)]
 | 
				
			||||||
struct Colors {
 | 
					struct Colors {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue