From e8fdd821195c1dc340063f2199ff3157222b0c60 Mon Sep 17 00:00:00 2001 From: mars Date: Sat, 14 May 2022 22:50:40 -0600 Subject: [PATCH] Refactor editor into Application struct --- editor/src/main.rs | 225 ++++++++++++++++++++++++++------------------- 1 file changed, 132 insertions(+), 93 deletions(-) diff --git a/editor/src/main.rs b/editor/src/main.rs index a984534..32b5331 100644 --- a/editor/src/main.rs +++ b/editor/src/main.rs @@ -1,51 +1,126 @@ +use egui_wgpu_backend::RenderPass as EguiRenderPass; +use std::sync::Arc; use egui_wgpu_backend::wgpu; use egui_winit::winit::{ self, event::{Event, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, + dpi::PhysicalSize, }; -async fn get_device( - window: &winit::window::Window, -) -> ( - wgpu::Device, - wgpu::Queue, - wgpu::Surface, - wgpu::SurfaceConfiguration, -) { - let size = window.inner_size(); - let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY); - let surface = unsafe { instance.create_surface(window) }; - let adapter = instance - .request_adapter(&wgpu::RequestAdapterOptions { - power_preference: wgpu::PowerPreference::LowPower, - compatible_surface: Some(&surface), - force_fallback_adapter: false, - }) - .await - .unwrap(); - let (device, queue) = adapter - .request_device( - &wgpu::DeviceDescriptor { - features: wgpu::Features::empty(), - limits: wgpu::Limits::default(), - label: None, - }, - None, - ) - .await - .unwrap(); - let config = wgpu::SurfaceConfiguration { - usage: wgpu::TextureUsages::RENDER_ATTACHMENT, - format: surface.get_preferred_format(&adapter).unwrap(), - width: size.width, - height: size.height, - present_mode: wgpu::PresentMode::Mailbox, - }; - surface.configure(&device, &config); +struct Application { + window: winit::window::Window, + device: Arc, + queue: Arc, + size: winit::dpi::PhysicalSize, + surface: wgpu::Surface, + config: wgpu::SurfaceConfiguration, + egui_state: egui_winit::State, + egui_ctx: egui::Context, + egui_rp: EguiRenderPass, +} - (device, queue, surface, config) +impl Application { + pub async fn new(window: winit::window::Window) -> Self { + let size = window.inner_size(); + let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY); + let surface = unsafe { instance.create_surface(&window) }; + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::LowPower, + compatible_surface: Some(&surface), + force_fallback_adapter: false, + }) + .await + .unwrap(); + let (device, queue) = adapter + .request_device( + &wgpu::DeviceDescriptor { + features: wgpu::Features::empty(), + limits: wgpu::Limits::default(), + label: None, + }, + None, + ) + .await + .unwrap(); + let config = wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + format: surface.get_preferred_format(&adapter).unwrap(), + width: size.width, + height: size.height, + present_mode: wgpu::PresentMode::Mailbox, + }; + surface.configure(&device, &config); + + let device = Arc::new(device); + let queue = Arc::new(queue); + + let egui_state = egui_winit::State::new(4096, &window); + let egui_ctx = egui::Context::default(); + let egui_rp = egui_wgpu_backend::RenderPass::new(&device, config.format, 1); + + Self { window, device, queue, size, surface, config, egui_state, egui_ctx, egui_rp } + } + + pub fn update(&mut self) { + self.window.request_redraw(); + } + + pub fn on_resize(&mut self, new_size: PhysicalSize) { + if new_size.width > 0 && new_size.height > 0 { + self.size = new_size; + self.config.width = new_size.width; + self.config.height = new_size.height; + self.surface.configure(&self.device, &self.config); + } + } + + pub fn render(&mut self) { + match self.surface.get_current_texture() { + Err(wgpu::SurfaceError::Lost) => self.on_resize(self.size), + Err(e) => panic!("Surface error: {:?}", e), + Ok(surface_texture) => { + let raw_input = self.egui_state.take_egui_input(&self.window); + let output = self.egui_ctx.run(raw_input, |ctx| { + egui::CentralPanel::default().show(ctx, |ui| { + egui::Window::new("example_window").show(ctx, |ui| { + ui.heading("Hello world!"); + }); + }); + }); + + self.egui_state.handle_platform_output( + &self.window, + &self.egui_ctx, + output.platform_output, + ); + + let meshes = self.egui_ctx.tessellate(output.shapes); + + let screen_desc = egui_wgpu_backend::ScreenDescriptor { + physical_width: self.config.width, + physical_height: self.config.height, + scale_factor: 1.0, // TODO ??? + }; + + self.egui_rp.update_buffers(&self.device, &self.queue, &meshes, &screen_desc); + self.egui_rp + .add_textures(&self.device, &self.queue, &output.textures_delta) + .unwrap(); + + let output_view = surface_texture.texture.create_view(&Default::default()); + let mut cmds = self.device.create_command_encoder(&Default::default()); + self.egui_rp + .execute(&mut cmds, &output_view, &meshes, &screen_desc, None) + .unwrap(); + self.queue.submit(std::iter::once(cmds.finish())); + surface_texture.present(); + self.egui_rp.remove_textures(output.textures_delta).unwrap(); + } + } + } } fn main() { @@ -56,69 +131,33 @@ fn main() { .build(&event_loop) .unwrap(); - let mut egui_state = egui_winit::State::new(4096, &window); - let egui_ctx = egui::Context::default(); - - let (device, queue, surface, surface_config) = pollster::block_on(get_device(&window)); - - let mut egui_rp = egui_wgpu_backend::RenderPass::new(&device, surface_config.format, 1); + let mut app = pollster::block_on(Application::new(window)); event_loop.run(move |event, _, control_flow| { *control_flow = ControlFlow::Wait; println!("{:?}", event); match event { - Event::WindowEvent { event, window_id } if window_id == window.id() => match event { - WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - event => { - egui_state.on_event(&egui_ctx, &event); - } - }, - Event::RedrawRequested(window_id) if window_id == window.id() => { - match surface.get_current_texture() { - // Err(wgpu::SurfaceError::Lost) => resize(), - Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit, - Err(e) => eprintln!("Surface error: {:?}", e), - Ok(surface_texture) => { - let raw_input = egui_state.take_egui_input(&window); - let output = egui_ctx.run(raw_input, |ctx| { - egui::CentralPanel::default().show(ctx, |ui| { - ui.heading("Hello world!"); - }); - }); - egui_state.handle_platform_output( - &window, - &egui_ctx, - output.platform_output, - ); - - let meshes = egui_ctx.tessellate(output.shapes); - - let screen_desc = egui_wgpu_backend::ScreenDescriptor { - physical_width: surface_config.width, - physical_height: surface_config.height, - scale_factor: 1.0, // TODO ??? - }; - - egui_rp.update_buffers(&device, &queue, &meshes, &screen_desc); - egui_rp - .add_textures(&device, &queue, &output.textures_delta) - .unwrap(); - - let output_view = surface_texture.texture.create_view(&Default::default()); - let mut cmds = device.create_command_encoder(&Default::default()); - egui_rp - .execute(&mut cmds, &output_view, &meshes, &screen_desc, None) - .unwrap(); - queue.submit(std::iter::once(cmds.finish())); - surface_texture.present(); - egui_rp.remove_textures(output.textures_delta).unwrap(); - } - } + Event::RedrawRequested(window_id) if window_id == app.window.id() => { + app.render(); } Event::MainEventsCleared => { - window.request_redraw(); + app.update(); } + Event::WindowEvent { event, window_id } if window_id == app.window.id() => { + match &event { + WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, + WindowEvent::Resized(physical_size) => { + app.on_resize(*physical_size); + } + WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { + app.on_resize(**new_inner_size); + } + _ => {} + } + + app.egui_state.on_event(&app.egui_ctx, &event); + }, _ => (), } });