use egui::{ClippedMesh, Context, TexturesDelta};
use egui_wgpu_backend::{BackendError, RenderPass, ScreenDescriptor};
use pixels::{wgpu, PixelsContext};
use winit::window::Window;
use crate::resources::ResourceManager;
pub(crate) struct Framework {
egui_ctx: Context,
egui_state: egui_winit::State,
screen_descriptor: ScreenDescriptor,
rpass: RenderPass,
paint_jobs: Vec<ClippedMesh>,
textures: TexturesDelta,
pub(crate) gui: Option<Box<dyn Fn(&Context, &mut ResourceManager)>>,
}
impl Framework {
pub(crate) fn new(width: u32, height: u32, scale_factor: f32, pixels: &pixels::Pixels) -> Self {
let max_texture_size = pixels.device().limits().max_texture_dimension_2d as usize;
let egui_ctx = Context::default();
let egui_state = egui_winit::State::from_pixels_per_point(max_texture_size, scale_factor);
let screen_descriptor = ScreenDescriptor {
physical_width: width,
physical_height: height,
scale_factor,
};
let rpass = RenderPass::new(pixels.device(), pixels.render_texture_format(), 1);
let textures = TexturesDelta::default();
Self {
egui_ctx,
egui_state,
screen_descriptor,
rpass,
paint_jobs: Vec::new(),
textures,
gui: None,
}
}
pub(crate) fn handle_event(&mut self, event: &winit::event::WindowEvent) {
self.egui_state.on_event(&self.egui_ctx, event);
}
pub(crate) fn prepare(&mut self, window: &Window, resources: &mut ResourceManager) {
let raw_input = self.egui_state.take_egui_input(window);
let output = self.egui_ctx.run(raw_input, |egui_ctx| {
if let Some(ui) = &self.gui {
ui(egui_ctx, resources);
}
});
self.textures.append(output.textures_delta);
self.egui_state
.handle_platform_output(window, &self.egui_ctx, output.platform_output);
self.paint_jobs = self.egui_ctx.tessellate(output.shapes);
}
pub(crate) fn render(
&mut self,
encoder: &mut wgpu::CommandEncoder,
render_target: &wgpu::TextureView,
context: &PixelsContext,
) -> Result<(), BackendError> {
self.rpass
.add_textures(&context.device, &context.queue, &self.textures)?;
self.rpass.update_buffers(
&context.device,
&context.queue,
&self.paint_jobs,
&self.screen_descriptor,
);
self.rpass.execute(
encoder,
render_target,
&self.paint_jobs,
&self.screen_descriptor,
None,
)?;
let textures = std::mem::take(&mut self.textures);
self.rpass.remove_textures(textures)
}
}