egui-raylib 0.1.2

Egui bindings for Raylib
Documentation
use std::collections::HashMap;

use egui::{ImageData, TextureId, TexturesDelta};
use raylib::{
    error::{LoadTextureError, UpdateTextureError},
    prelude::*,
};

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

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

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

fn map_texture_filter(filter: egui::TextureFilter) -> TextureFilter {
    match filter {
        egui::TextureFilter::Nearest => TextureFilter::TEXTURE_FILTER_POINT,
        egui::TextureFilter::Linear => TextureFilter::TEXTURE_FILTER_BILINEAR,
    }
}

fn map_texture_wrap_mode(wrap: egui::TextureWrapMode) -> TextureWrap {
    match wrap {
        egui::TextureWrapMode::ClampToEdge => TextureWrap::TEXTURE_WRAP_CLAMP,
        egui::TextureWrapMode::Repeat => TextureWrap::TEXTURE_WRAP_REPEAT,
        egui::TextureWrapMode::MirroredRepeat => TextureWrap::TEXTURE_WRAP_MIRROR_REPEAT,
    }
}

pub(crate) fn handle_textures(
    map: &mut HashMap<TextureId, Texture2D>,
    d: &mut RaylibDrawHandle,
    thread: &RaylibThread,
    textures_delta: &TexturesDelta,
) -> Result<(), HandleTexturesErrors> {
    for (id, image_delta) in textures_delta.set.iter() {
        let image_width = image_delta.image.width();
        let image_height = image_delta.image.height();

        let options = image_delta.options;

        match &image_delta.image {
            ImageData::Color(color_image) => {
                let bytes = color_image
                    .pixels
                    .iter()
                    .flat_map(|x| [x.r(), x.g(), x.b(), x.a()])
                    .collect::<Vec<u8>>();

                if let Some(texture) = map.get_mut(&id) {
                    texture.set_texture_filter(thread, map_texture_filter(options.minification));
                    texture.set_texture_wrap(thread, map_texture_wrap_mode(options.wrap_mode));
                    if let Some(pos) = image_delta.pos {
                        texture.update_texture_rec(
                            Rectangle::new(
                                pos[0] as f32,
                                pos[1] as f32,
                                image_width as f32,
                                image_height as f32,
                            ),
                            &bytes,
                        )?;
                    } else {
                        if image_width as i32 == texture.width
                            && image_height as i32 == texture.height
                        {
                            texture.update_texture(&bytes)?;
                        } else {
                            let image = Image::gen_image_color(
                                image_width as i32,
                                image_height as i32,
                                Color::BLACK,
                            );
                            *texture = d.load_texture_from_image(thread, &image)?;
                            texture.update_texture(&bytes)?;
                        }
                    }
                } else {
                    let rl_image = Image::gen_image_color(
                        image_width as i32,
                        image_height as i32,
                        Color::BLACK,
                    );
                    let mut new_texture = d.load_texture_from_image(thread, &rl_image)?;
                    new_texture
                        .set_texture_filter(thread, map_texture_filter(options.minification));
                    new_texture.set_texture_wrap(thread, map_texture_wrap_mode(options.wrap_mode));
                    new_texture.update_texture(&bytes)?;

                    map.insert(*id, new_texture);
                }
            }
        }
    }

    for id in textures_delta.free.iter() {
        map.remove(&id);
    }

    Ok(())
}