flatbox_egui 0.1.0

Egui binding for Flatbox engine
Documentation
use std::sync::Arc;
use parking_lot::Mutex;

use flatbox_render::{
    error::RenderError, 
    context::{Context, Display, WindowEvent},
    renderer::Renderer,
};
use crate::painter::Painter;

pub struct EguiBackend {
    pub egui_ctx: egui::Context,
    pub state: Arc<Mutex<egui_winit::State>>,
    pub painter: Painter,

    shapes: Vec<egui::epaint::ClippedShape>,
    textures_delta: egui::TexturesDelta,
}

impl EguiBackend {
    pub fn new(context: &Context) -> Self {
        let painter = Painter::new().expect("Cannot initialize egui backend");

        let mut state = egui_winit::State::new(context.event_loop_target());
        state.set_max_texture_side(2048);

        let pixels_per_point = context.display().lock().window().scale_factor() as f32;
        state.set_pixels_per_point(pixels_per_point);

        Self {
            egui_ctx: egui::Context::default(),
            state: Arc::new(Mutex::new(state)),
            painter,
            shapes: Default::default(),
            textures_delta: Default::default(),
        }
    }

    pub fn context(&self) -> &egui::Context {
        &self.egui_ctx
    }

    pub fn on_event(&mut self, event: &WindowEvent<'_>) -> bool {
        self.state.lock().on_event(&self.egui_ctx, event)
    }

    pub fn run(
        &mut self,
        display: Display,
        run_ui: impl FnMut(&egui::Context),
    ) -> std::time::Duration {
        let raw_input = self.state.lock().take_egui_input(display.lock().window());
        let egui::FullOutput {
            platform_output,
            repaint_after,
            textures_delta,
            shapes,
        } = self.egui_ctx.run(raw_input, run_ui);

        self.state.lock()
            .handle_platform_output(display.lock().window(), &self.egui_ctx, platform_output);

        self.shapes = shapes;
        self.textures_delta.append(textures_delta);

        repaint_after
    }

    pub fn paint(&mut self, renderer: &mut Renderer) -> Result<(), RenderError> {
        let shapes = std::mem::take(&mut self.shapes);
        let textures_delta = std::mem::take(&mut self.textures_delta);
        let clipped_primitives = self.egui_ctx.tessellate(shapes);

        let pixels_per_point = self.egui_ctx.pixels_per_point();
        let screen_size_px = renderer.extent().into();

        self.painter.paint_and_update_textures(
            renderer,
            screen_size_px,
            pixels_per_point,
            &clipped_primitives,
            &textures_delta,
        )?;

        Ok(())
    }
}