use egui::{Context}; use egui_wgpu::Renderer; use egui_winit::{EventResponse, State}; use wgpu::{CommandEncoder, CommandEncoderDescriptor, Operations, RenderPassDescriptor, TextureView}; use winit::{event::WindowEvent, window::{Theme, Window}}; use crate::wgpuctx::WgpuCtx; pub struct EguiCtx { state: State, renderer: Renderer, context: Context, ready: bool } impl EguiCtx { pub fn new( window: &winit::window::Window, wgpuctx: &WgpuCtx) -> Self { let ctx = egui::Context::default(); let viewport_id = ctx.viewport_id(); let state = egui_winit::State::new( ctx.clone(), viewport_id, window, Some(window.scale_factor() as _), Some(Theme::Light), None); let renderer = Renderer::new( wgpuctx.device(), wgpuctx.surface_config().format, egui_wgpu::RendererOptions { depth_stencil_format: None, msaa_samples: 1, ..Default::default() } ); Self { context: ctx, state: state, renderer: renderer, ready: false } } pub fn context(&self) -> &Context { self.state.egui_ctx() } pub fn window_event( &mut self, window: &Window, event: &WindowEvent) -> EventResponse { self.state.on_window_event(window, event) } pub fn prepare( &mut self, window: &Window) { let raw_input = self.state.take_egui_input(window); self.context().begin_pass(raw_input); self.ready = true; } pub fn present( &mut self, window: &Window, wgpuctx: &WgpuCtx, encoder: &mut CommandEncoder, view: &TextureView) { if !self.ready { return; } self.ready = false; let full_output = self.context().end_pass(); self.state.handle_platform_output(window, full_output.platform_output); let jobs = self.context().tessellate( full_output.shapes, full_output.pixels_per_point ); let screen_descriptor = { let view_size = view.texture().size(); let (width, height) = (view_size.width, view_size.height); egui_wgpu::ScreenDescriptor { size_in_pixels: [width, height], pixels_per_point: full_output.pixels_per_point } }; for (id, image_delta) in full_output.textures_delta.set { self.renderer.update_texture(wgpuctx.device(), wgpuctx.queue(), id, &image_delta); } self.renderer.update_buffers( wgpuctx.device(), wgpuctx.queue(), encoder, &jobs, &screen_descriptor ); { let mut render_pass = encoder.begin_render_pass(&RenderPassDescriptor { label: Some("EguiCtx render pass"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: view, resolve_target: None, ops: Operations { load: wgpu::LoadOp::Load, store: wgpu::StoreOp::Store }, depth_slice: None })], depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None }); self.renderer.render( &mut render_pass.forget_lifetime(), &jobs, &screen_descriptor ); } for id in &full_output.textures_delta.free { self.renderer.free_texture(id); } } }