ranim_core/components/
rgba.rs

1use std::ops::{Deref, DerefMut};
2
3// use bevy_color::{ColorToComponents, LinearRgba};
4use color::{AlphaColor, ColorSpace, LinearSrgb, Srgb};
5use glam::{Vec4, vec4};
6
7use crate::{
8    components::PointVec,
9    prelude::{Interpolatable, Opacity},
10};
11
12/// Rgba
13#[repr(C)]
14#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
15pub struct Rgba(pub Vec4);
16
17impl Opacity for Rgba {
18    fn set_opacity(&mut self, opacity: f32) -> &mut Self {
19        self.0.w = opacity;
20        self
21    }
22}
23
24impl Opacity for PointVec<Rgba> {
25    fn set_opacity(&mut self, opacity: f32) -> &mut Self {
26        self.iter_mut().for_each(|rgba| {
27            rgba.set_opacity(opacity);
28        });
29        self
30    }
31}
32
33impl<CS: ColorSpace> From<AlphaColor<CS>> for Rgba {
34    fn from(value: AlphaColor<CS>) -> Self {
35        let rgba = value.convert::<LinearSrgb>().components;
36        Self(Vec4::from_array(rgba))
37    }
38}
39
40impl From<Rgba> for AlphaColor<Srgb> {
41    fn from(value: Rgba) -> AlphaColor<Srgb> {
42        let linear_rgba = value.0.to_array();
43        AlphaColor::<LinearSrgb>::new(linear_rgba).convert()
44    }
45}
46
47// impl From<bevy_color::Srgba> for Rgba {
48//     fn from(value: bevy_color::Srgba) -> Self {
49//         let rgba = LinearRgba::from(value);
50//         Self(rgba.to_vec4())
51//     }
52// }
53
54impl Default for Rgba {
55    fn default() -> Self {
56        vec4(1.0, 0.0, 0.0, 1.0).into()
57    }
58}
59
60impl From<Vec4> for Rgba {
61    fn from(value: Vec4) -> Self {
62        Self(value)
63    }
64}
65
66impl Deref for Rgba {
67    type Target = Vec4;
68    fn deref(&self) -> &Self::Target {
69        &self.0
70    }
71}
72
73impl DerefMut for Rgba {
74    fn deref_mut(&mut self) -> &mut Self::Target {
75        &mut self.0
76    }
77}
78
79impl Interpolatable for Rgba {
80    fn lerp(&self, target: &Self, t: f64) -> Self {
81        Self(self.0.lerp(target.0, t as f32))
82    }
83}
84
85#[cfg(test)]
86mod test {
87    use super::*;
88
89    #[test]
90    fn test_convertion() {
91        let approx = |a: f32, b: f32| (a - b).abs() < 0.001;
92        // The `rgb8` and `rgba8` should be in srgb
93        let color = AlphaColor::from_rgb8(85, 133, 217);
94        assert!(approx(color.components[0], 0.333));
95        assert!(approx(color.components[1], 0.522));
96        assert!(approx(color.components[2], 0.851));
97
98        let linear_rgba = Rgba::from(color);
99        assert!(approx(linear_rgba.x, 0.091));
100        assert!(approx(linear_rgba.y, 0.235));
101        assert!(approx(linear_rgba.z, 0.694));
102    }
103}