egui-raylib 0.1.1

Egui bindings for Raylib
mod input;
mod output;
mod renderer;
mod textures;

use std::collections::HashMap;

use egui::{ClippedPrimitive, Context, TextureId, TexturesDelta, Ui};
use raylib::prelude::*;

use crate::textures::HandleTexturesErrors;

#[derive(Debug)]
pub enum EguiRaylibError {
    HandleTexturesErrors(HandleTexturesErrors),
}

impl From<HandleTexturesErrors> for EguiRaylibError {
    fn from(value: HandleTexturesErrors) -> Self {
        EguiRaylibError::HandleTexturesErrors(value)
    }
}

pub struct EguiRaylib {
    ctx: egui::Context,
    textures: HashMap<TextureId, Texture2D>,
    pixels_per_point: f32,
    last_textures_delta: Option<TexturesDelta>,
    last_clipped_primitives: Option<Vec<ClippedPrimitive>>,
}

impl EguiRaylib {
    pub fn new(ctx: egui::Context, pixels_per_point: f32) -> Self {
        Self {
            ctx,
            textures: HashMap::new(),
            last_textures_delta: None,
            last_clipped_primitives: None,
            pixels_per_point: pixels_per_point,
        }
    }

    pub fn ctx(&self) -> &Context {
        &self.ctx
    }

    pub fn run(&mut self, rl: &mut RaylibHandle, run_ui: impl FnMut(&mut Ui)) {
        let raw_input: egui::RawInput = input::gather_input(rl, self.pixels_per_point);

        let full_output = self.ctx.run_ui(raw_input, run_ui);

        output::handle_platform_output(rl, full_output.platform_output);

        self.pixels_per_point = full_output.pixels_per_point;
        self.last_clipped_primitives = Some(
            self.ctx
                .tessellate(full_output.shapes, full_output.pixels_per_point),
        );

        self.last_textures_delta = Some(full_output.textures_delta);
    }

    pub fn draw(
        &mut self,
        d: &mut RaylibDrawHandle,
        thread: &RaylibThread,
    ) -> Result<(), EguiRaylibError> {
        if let Some(textures_delta) = &self.last_textures_delta {
            match textures::handle_textures(&mut self.textures, d, &thread, &textures_delta) {
                Ok(()) => self.last_textures_delta = None,
                Err(err) => return Err(err.into()),
            }
        }

        if let Some(clipped_primitives) = self.last_clipped_primitives.take() {
            renderer::render(
                d,
                self.pixels_per_point,
                &clipped_primitives,
                &self.textures,
            );
        }

        Ok(())
    }
}

impl Default for EguiRaylib {
    fn default() -> Self {
        Self::new(egui::Context::default(), 1.)
    }
}