1use std::fmt;
17
18use crate::sys;
19
20#[repr(C)]
22#[derive(Copy, Clone, Debug, PartialEq)]
23pub struct Color {
24 pub r: f32,
25 pub g: f32,
26 pub b: f32,
27 pub a: f32,
28}
29
30impl Color {
31 pub const fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
32 Self { r, g, b, a }
33 }
34 pub const fn rgb(r: f32, g: f32, b: f32) -> Self {
35 Self::new(r, g, b, 1.0)
36 }
37 pub fn from_rgba_bytes(r: u8, g: u8, b: u8, a: u8) -> Self {
38 Self::new(
39 r as f32 / 255.0,
40 g as f32 / 255.0,
41 b as f32 / 255.0,
42 a as f32 / 255.0,
43 )
44 }
45 pub fn from_rgb_bytes(r: u8, g: u8, b: u8) -> Self {
46 Self::from_rgba_bytes(r, g, b, 255)
47 }
48 pub fn from_imgui_u32(abgr: u32) -> Self {
53 unsafe {
54 let v = sys::igColorConvertU32ToFloat4(abgr);
55 Self::new(v.x, v.y, v.z, v.w)
56 }
57 }
58
59 pub fn from_rgb_u32(rgb: u32) -> Self {
61 Self::from_rgba_bytes(
62 ((rgb >> 16) & 0xFF) as u8,
63 ((rgb >> 8) & 0xFF) as u8,
64 (rgb & 0xFF) as u8,
65 255,
66 )
67 }
68
69 pub fn to_imgui_u32(self) -> u32 {
71 unsafe {
72 sys::igColorConvertFloat4ToU32(sys::ImVec4_c {
73 x: self.r,
74 y: self.g,
75 z: self.b,
76 w: self.a,
77 })
78 }
79 }
80 pub fn to_array(self) -> [f32; 4] {
81 [self.r, self.g, self.b, self.a]
82 }
83 pub fn from_array(arr: [f32; 4]) -> Self {
84 Self::new(arr[0], arr[1], arr[2], arr[3])
85 }
86 pub fn with_alpha(mut self, alpha: f32) -> Self {
87 self.a = alpha;
88 self
89 }
90 pub fn lerp(self, other: Self, t: f32) -> Self {
91 let t = t.clamp(0.0, 1.0);
92 Self::new(
93 self.r + (other.r - self.r) * t,
94 self.g + (other.g - self.g) * t,
95 self.b + (other.b - self.b) * t,
96 self.a + (other.a - self.a) * t,
97 )
98 }
99
100 #[doc(alias = "ColorConvertRGBtoHSV")]
104 pub fn to_hsv01(self) -> (f32, f32, f32) {
105 let mut h = 0.0;
106 let mut s = 0.0;
107 let mut v = 0.0;
108 unsafe {
109 sys::igColorConvertRGBtoHSV(self.r, self.g, self.b, &mut h, &mut s, &mut v);
110 }
111 (h, s, v)
112 }
113
114 #[doc(alias = "ColorConvertHSVtoRGB")]
118 pub fn from_hsv01(h: f32, s: f32, v: f32) -> Self {
119 let mut r = 0.0;
120 let mut g = 0.0;
121 let mut b = 0.0;
122 unsafe {
123 sys::igColorConvertHSVtoRGB(h, s, v, &mut r, &mut g, &mut b);
124 }
125 Self::rgb(r, g, b)
126 }
127
128 pub fn to_hsv(self) -> (f32, f32, f32) {
129 let max = self.r.max(self.g).max(self.b);
130 let min = self.r.min(self.g).min(self.b);
131 let delta = max - min;
132 let h = if delta == 0.0 {
133 0.0
134 } else if max == self.r {
135 60.0 * (((self.g - self.b) / delta) % 6.0)
136 } else if max == self.g {
137 60.0 * (((self.b - self.r) / delta) + 2.0)
138 } else {
139 60.0 * (((self.r - self.g) / delta) + 4.0)
140 };
141 let s = if max == 0.0 { 0.0 } else { delta / max };
142 let v = max;
143 (h, s, v)
144 }
145 pub fn from_hsv(h: f32, s: f32, v: f32) -> Self {
146 let h = h % 360.0;
147 let c = v * s;
148 let x = c * (1.0 - ((h / 60.0) % 2.0 - 1.0).abs());
149 let m = v - c;
150 let (r, g, b) = if h < 60.0 {
151 (c, x, 0.0)
152 } else if h < 120.0 {
153 (x, c, 0.0)
154 } else if h < 180.0 {
155 (0.0, c, x)
156 } else if h < 240.0 {
157 (0.0, x, c)
158 } else if h < 300.0 {
159 (x, 0.0, c)
160 } else {
161 (c, 0.0, x)
162 };
163 Self::new(r + m, g + m, b + m, 1.0)
164 }
165}
166
167impl Default for Color {
168 fn default() -> Self {
169 Self::new(1.0, 1.0, 1.0, 1.0)
170 }
171}
172impl From<[f32; 4]> for Color {
173 fn from(arr: [f32; 4]) -> Self {
174 Self::from_array(arr)
175 }
176}
177impl From<Color> for [f32; 4] {
178 fn from(color: Color) -> Self {
179 color.to_array()
180 }
181}
182impl From<(f32, f32, f32, f32)> for Color {
183 fn from((r, g, b, a): (f32, f32, f32, f32)) -> Self {
184 Self::new(r, g, b, a)
185 }
186}
187impl From<Color> for (f32, f32, f32, f32) {
188 fn from(color: Color) -> Self {
189 (color.r, color.g, color.b, color.a)
190 }
191}
192
193impl fmt::Display for Color {
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 write!(
196 f,
197 "rgba({:.3}, {:.3}, {:.3}, {:.3})",
198 self.r, self.g, self.b, self.a
199 )
200 }
201}
202
203impl Color {
205 pub const TRANSPARENT: Color = Color::new(0.0, 0.0, 0.0, 0.0);
206 pub const BLACK: Color = Color::new(0.0, 0.0, 0.0, 1.0);
207 pub const WHITE: Color = Color::new(1.0, 1.0, 1.0, 1.0);
208 pub const RED: Color = Color::new(1.0, 0.0, 0.0, 1.0);
209 pub const GREEN: Color = Color::new(0.0, 1.0, 0.0, 1.0);
210 pub const BLUE: Color = Color::new(0.0, 0.0, 1.0, 1.0);
211 pub const YELLOW: Color = Color::new(1.0, 1.0, 0.0, 1.0);
212 pub const CYAN: Color = Color::new(0.0, 1.0, 1.0, 1.0);
213 pub const MAGENTA: Color = Color::new(1.0, 0.0, 1.0, 1.0);
214}