lumecs 0.0.1

Experimental GUI backed by Bevy ECS + usual suspects
use std::fmt::Display;

use bevy_color::prelude::*;
use bevy_ecs::prelude::*;

#[derive(Component, Debug, Clone, Copy, PartialEq)]
pub struct Color(pub Srgba);

impl Default for Color {
    fn default() -> Self {
        Color::white()
    }
}

impl Color {
    pub fn hex(value: impl Into<String>) -> Self {
        let value = value.into();
        Srgba::hex(&value)
            .map(Color)
            .unwrap_or_else(|_| panic!("Invalid color hex string: {value}"))
    }

    pub const fn black() -> Color {
        Color(Srgba::new(0.0, 0.0, 0.0, 1.0))
    }

    pub const fn white() -> Color {
        Color(Srgba::new(1.0, 1.0, 1.0, 1.0))
    }

    pub const fn transparent() -> Color {
        Color(Srgba::new(0.0, 0.0, 0.0, 0.0))
    }
}

impl From<&str> for Color {
    fn from(value: &str) -> Self {
        Self::hex(value)
    }
}

impl Display for Color {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "#{:02X}{:02X}{:02X}{:02X}",
            (self.0.red * 255.0) as u8,
            (self.0.green * 255.0) as u8,
            (self.0.blue * 255.0) as u8,
            (self.0.alpha * 255.0) as u8,
        )
    }
}

pub trait ColorExt {
    fn color(self, color: impl Into<Color>) -> Self;
}

impl From<&Color> for vello::peniko::Color {
    fn from(value: &Color) -> Self {
        vello::peniko::Color::new([value.0.red, value.0.green, value.0.blue, value.0.alpha])
    }
}

impl From<Color> for vello::peniko::Color {
    fn from(value: Color) -> Self {
        Self::from(&value)
    }
}

pub mod prelude {
    pub use super::ColorExt;
}