#![allow(clippy::multiple_bound_locations)] #[repr(C)] #[derive(Clone, Copy, bytemuck::Zeroable, Debug)] pub struct Color { pub r: T, pub g: T, pub b: T, pub a: T, } impl Color { pub const BLACK: Self = Self::rgb(T::MIN, T::MIN, T::MIN); pub const WHITE: Self = Self::rgb(T::MAX, T::MAX, T::MAX); pub const RED: Self = Self::rgb(T::MAX, T::MIN, T::MIN); pub const ORANGE: Self = Self::rgb(T::MAX, T::MID, T::MIN); pub const YELLOW: Self = Self::rgb(T::MAX, T::MAX, T::MIN); pub const LIME: Self = Self::rgb(T::MID, T::MAX, T::MIN); pub const GREEN: Self = Self::rgb(T::MIN, T::MAX, T::MIN); pub const TURQUOISE: Self = Self::rgb(T::MIN, T::MAX, T::MID); pub const CYAN: Self = Self::rgb(T::MIN, T::MAX, T::MAX); pub const SKY: Self = Self::rgb(T::MIN, T::MID, T::MAX); pub const BLUE: Self = Self::rgb(T::MIN, T::MIN, T::MAX); pub const PURPLE: Self = Self::rgb(T::MID, T::MIN, T::MAX); pub const MAGENTA: Self = Self::rgb(T::MAX, T::MIN, T::MAX); pub const fn new(r: T, g: T, b: T, a: T) -> Self { Self { r, g, b, a } } pub const fn rgb(r: T, g: T, b: T) -> Self { Self { r, g, b, a: T::MAX } } pub fn alpha(mut self, a: T) -> Self { self.a = a; self } } pub trait ColorNum { const MIN: Self; const MID: Self; const MAX: Self; } impl ColorNum for u8 { const MIN: Self = u8::MIN; const MID: Self = u8::MAX / 2; const MAX: Self = u8::MAX; } impl ColorNum for f32 { const MIN: Self = 0.0; const MID: Self = 0.5; const MAX: Self = 1.0; } unsafe impl bytemuck::Pod for Color {} pub trait F32Conversion { fn to(self) -> f32; fn from(x: f32) -> Self; } impl Color { pub fn mul_rgb(self, x: impl F32Conversion) -> Self { let x = x.to(); Self { r: T::from(self.r.to() * x), g: T::from(self.g.to() * x), b: T::from(self.b.to() * x), a: self.a, } } pub fn add_rgb(self, x: impl F32Conversion) -> Self { let x = x.to(); Self { r: T::from(self.r.to() + x), g: T::from(self.g.to() + x), b: T::from(self.b.to() + x), a: self.a, } } } impl F32Conversion for f32 { fn to(self) -> f32 { self } fn from(x: f32) -> Self { x } } impl F32Conversion for u8 { fn to(self) -> f32 { self as f32 / 255.0 } fn from(x: f32) -> Self { (x * 255.0).clamp(0.0, 255.0) as Self } }