ranim_core/components/
rgba.rs1use std::ops::{Deref, DerefMut};
2
3use color::{AlphaColor, ColorSpace, LinearSrgb, Srgb};
5use glam::{Vec4, vec4};
6
7use crate::{
8 components::PointVec,
9 prelude::{Interpolatable, Opacity},
10};
11
12#[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
47impl 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 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}