use std::sync::Arc;
use egui::{ClippedPrimitive, Context, FullOutput};
use egui_wgpu::{Renderer, RendererOptions, ScreenDescriptor};
use wgpu::{self, CommandEncoder, Device, Queue, TextureFormat};
use winit::window::Window;
use crate::{
graphics::GraphicsState,
types::{EngineUpdates, Scene},
};
pub(crate) struct GuiState {
pub egui_state: egui_winit::State,
pub egui_renderer: Renderer,
pub mouse_in_gui: bool,
pub size: (f32, f32),
}
impl GuiState {
pub fn new(
window: Arc<Window>,
device: &Device,
texture_format: TextureFormat,
_msaa_samples: u32,
) -> Self {
let egui_context = Context::default();
let egui_state = egui_winit::State::new(
egui_context,
egui::viewport::ViewportId::ROOT,
&window,
Some(window.scale_factor() as f32),
None,
None,
);
let egui_renderer = Renderer::new(
device,
texture_format,
RendererOptions {
msaa_samples: 1,
depth_stencil_format: None,
dithering: false,
predictable_texture_filtering: false,
},
);
Self {
egui_state,
egui_renderer,
mouse_in_gui: false,
size: (0., 0.),
}
}
pub(crate) fn render_gui_pre_rpass<T>(
&mut self,
graphics: &mut GraphicsState,
user_state: &mut T,
device: &Device,
mut gui_handler: impl FnMut(&mut T, &Context, &mut Scene) -> EngineUpdates,
encoder: &mut CommandEncoder,
queue: &Queue,
width: u32,
height: u32,
updates_gui: &mut EngineUpdates,
) -> (FullOutput, Vec<ClippedPrimitive>, ScreenDescriptor, bool) {
let screen_descriptor = ScreenDescriptor {
size_in_pixels: [width, height],
pixels_per_point: graphics.window.scale_factor() as f32,
};
self.egui_state
.egui_ctx()
.set_pixels_per_point(screen_descriptor.pixels_per_point);
let mut resize_required = false;
let raw_input = self.egui_state.take_egui_input(&graphics.window);
let full_output = self.egui_state.egui_ctx().run(raw_input, |ctx| {
*updates_gui = gui_handler(user_state, ctx, &mut graphics.scene);
let new_size = updates_gui.ui_reserved_px;
if self.size != new_size {
resize_required = true;
self.size = new_size;
graphics.scene.gui_size = self.size;
}
});
self.egui_state
.handle_platform_output(&graphics.window, full_output.platform_output.clone());
let tris = self.egui_state.egui_ctx().tessellate(
full_output.shapes.clone(), self.egui_state.egui_ctx().pixels_per_point(),
);
for (id, image_delta) in &full_output.textures_delta.set {
self.egui_renderer
.update_texture(device, queue, *id, image_delta);
}
self.egui_renderer
.update_buffers(device, queue, encoder, &tris, &screen_descriptor);
(full_output, tris, screen_descriptor, resize_required)
}
}