cotis-raylib 0.1.0-alpha

Raylib-backed renderer for Cotis
Documentation
//! Path-based image types for raylib texture loading.
//!
//! Re-exports [`JPEGImage`], [`PNGImage`], and [`SVGImage`] from `cotis-defaults` and provides
//! [`PathBasedImage`] as a unified enum. All variants store a filesystem path; textures are loaded
//! via [`RaylibRender::translate_generic_image`](crate::renderer::RaylibRender::translate_generic_image).
//!
//! [`SVGImage`] is a semantic path tag — raylib loads raster data from the path. True vector SVG
//! rendering is not implemented; use pre-rasterized assets until dedicated support lands.

use std::fmt::{self, Debug, Formatter};
use std::sync::Arc;

use raylib::texture::Texture2D;

use crate::drawables::RaylibDrawContext;
use crate::raylib_images::{GenericCompatibleImage, RaylibLoadableImage};

/// JPEG path wrapper from `cotis-defaults`.
pub use cotis_defaults::generic_image::{JPEGImage, PNGImage, SVGImage};

/// Unified path-based image enum covering all supported file kinds.
#[derive(Clone)]
pub enum PathBasedImage {
    /// JPEG image referenced by filesystem path.
    Jpeg(JPEGImage),
    /// PNG image referenced by filesystem path.
    Png(PNGImage),
    /// SVG path tag (loads raster data from path via raylib; no vector rasterizer).
    Svg(SVGImage),
}

impl Debug for PathBasedImage {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            PathBasedImage::Jpeg(image) => f.debug_tuple("Jpeg").field(&image.get_path()).finish(),
            PathBasedImage::Png(image) => f.debug_tuple("Png").field(&image.get_path()).finish(),
            PathBasedImage::Svg(image) => f.debug_tuple("Svg").field(&image.get_path()).finish(),
        }
    }
}

impl PathBasedImage {
    /// Returns the filesystem path string used as the texture cache key.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// use cotis_defaults::generic_image::JPEGImage;
    /// use cotis_raylib::cotis_defaults_images::PathBasedImage;
    ///
    /// let image = PathBasedImage::Jpeg(JPEGImage::new_const("./assets/icon.jpg"));
    /// assert_eq!(image.path(), "./assets/icon.jpg");
    /// ```
    pub fn path(&self) -> &str {
        match self {
            PathBasedImage::Jpeg(image) => image.get_path(),
            PathBasedImage::Png(image) => image.get_path(),
            PathBasedImage::Svg(image) => image.get_path(),
        }
    }
}

macro_rules! impl_path_image {
    ($ty:ty) => {
        impl RaylibLoadableImage for $ty {
            fn get_filename(&self) -> &str {
                self.get_path()
            }
        }

        impl GenericCompatibleImage for $ty {
            fn load_texture(&self, _ctx: &mut RaylibDrawContext<'_, '_>) {}

            fn get_texture(&self, ctx: &RaylibDrawContext<'_, '_>) -> Arc<Texture2D> {
                let path = self.get_path();
                let cache = ctx
                    .image_cache
                    .expect("image drawing requires RaylibDrawContext::image_cache");
                cache
                    .get(path)
                    .cloned()
                    .unwrap_or_else(|| panic!("image not preloaded: {path}"))
            }
        }
    };
}

impl_path_image!(JPEGImage);
impl_path_image!(PNGImage);
impl_path_image!(SVGImage);

impl RaylibLoadableImage for PathBasedImage {
    fn get_filename(&self) -> &str {
        self.path()
    }
}

impl GenericCompatibleImage for PathBasedImage {
    fn load_texture(&self, ctx: &mut RaylibDrawContext<'_, '_>) {
        match self {
            PathBasedImage::Jpeg(image) => image.load_texture(ctx),
            PathBasedImage::Png(image) => image.load_texture(ctx),
            PathBasedImage::Svg(image) => image.load_texture(ctx),
        }
    }

    fn get_texture(&self, ctx: &RaylibDrawContext<'_, '_>) -> Arc<Texture2D> {
        match self {
            PathBasedImage::Jpeg(image) => image.get_texture(ctx),
            PathBasedImage::Png(image) => image.get_texture(ctx),
            PathBasedImage::Svg(image) => image.get_texture(ctx),
        }
    }
}