1use glam::{Vec3, Vec4};
4use std::ops::{Add, AddAssign, Mul, MulAssign};
5use thiserror::Error;
6
7use crate::prelude::*;
8
9#[derive(Clone, Copy, Debug, HasSchema)]
11#[derive_type_data(SchemaDeserialize)]
12pub enum Color {
13 Rgba {
15 red: f32,
17 green: f32,
19 blue: f32,
21 alpha: f32,
23 },
24}
25
26#[cfg(feature = "ui")]
27impl From<Color> for egui::Color32 {
28 fn from(value: Color) -> Self {
29 match value {
30 Color::Rgba {
31 red,
32 green,
33 blue,
34 alpha,
35 } => egui::Rgba::from_srgba_unmultiplied(
36 (red * 255.0) as u8,
37 (green * 255.0) as u8,
38 (blue * 255.0) as u8,
39 (alpha * 255.0) as u8,
40 )
41 .into(),
42 }
43 }
44}
45
46impl<'de> serde::Deserialize<'de> for Color {
47 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
48 where
49 D: serde::Deserializer<'de>,
50 {
51 deserializer.deserialize_str(ColorVisitor)
52 }
53}
54
55struct ColorVisitor;
56impl<'de> serde::de::Visitor<'de> for ColorVisitor {
57 type Value = Color;
58 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
59 write!(formatter, "A color in any valid CSS color format")
60 }
61
62 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
63 where
64 E: serde::de::Error,
65 {
66 let color = csscolorparser::parse(v).map_err(|e| E::custom(e.to_string()))?;
67 Ok(Color::Rgba {
68 red: color.r as f32,
69 green: color.g as f32,
70 blue: color.b as f32,
71 alpha: color.a as f32,
72 })
73 }
74}
75
76impl Color {
77 pub const BLACK: Color = Color::rgb(0.0, 0.0, 0.0);
79 pub const BLUE: Color = Color::rgb(0.0, 0.0, 1.0);
81 pub const CYAN: Color = Color::rgb(0.0, 1.0, 1.0);
83 pub const GRAY: Color = Color::rgb(0.5, 0.5, 0.5);
85 pub const GREEN: Color = Color::rgb(0.0, 1.0, 0.0);
87 pub const NONE: Color = Color::rgba(0.0, 0.0, 0.0, 0.0);
89 pub const ORANGE: Color = Color::rgb(1.0, 0.65, 0.0);
91 pub const RED: Color = Color::rgb(1.0, 0.0, 0.0);
93 pub const WHITE: Color = Color::rgb(1.0, 1.0, 1.0);
95 pub const YELLOW: Color = Color::rgb(1.0, 1.0, 0.0);
97
98 pub const fn rgb(r: f32, g: f32, b: f32) -> Color {
109 Color::Rgba {
110 red: r,
111 green: g,
112 blue: b,
113 alpha: 1.0,
114 }
115 }
116
117 pub const fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color {
129 Color::Rgba {
130 red: r,
131 green: g,
132 blue: b,
133 alpha: a,
134 }
135 }
136
137 pub fn hex<T: AsRef<str>>(hex: T) -> Result<Color, HexColorError> {
148 let hex = hex.as_ref();
149
150 if hex.len() == 3 {
152 let mut data = [0; 6];
153 for (i, ch) in hex.chars().enumerate() {
154 data[i * 2] = ch as u8;
155 data[i * 2 + 1] = ch as u8;
156 }
157 return decode_rgb(&data);
158 }
159
160 if hex.len() == 4 {
162 let mut data = [0; 8];
163 for (i, ch) in hex.chars().enumerate() {
164 data[i * 2] = ch as u8;
165 data[i * 2 + 1] = ch as u8;
166 }
167 return decode_rgba(&data);
168 }
169
170 if hex.len() == 6 {
172 return decode_rgb(hex.as_bytes());
173 }
174
175 if hex.len() == 8 {
177 return decode_rgba(hex.as_bytes());
178 }
179
180 Err(HexColorError::Length)
181 }
182
183 pub fn rgb_u8(r: u8, g: u8, b: u8) -> Color {
194 Color::rgba_u8(r, g, b, u8::MAX)
195 }
196
197 pub fn rgba_u8(r: u8, g: u8, b: u8, a: u8) -> Color {
211 Color::rgba(
212 r as f32 / u8::MAX as f32,
213 g as f32 / u8::MAX as f32,
214 b as f32 / u8::MAX as f32,
215 a as f32 / u8::MAX as f32,
216 )
217 }
218
219 pub fn r(&self) -> f32 {
221 match self.as_rgba() {
222 Color::Rgba { red, .. } => red,
223 }
224 }
225
226 pub fn g(&self) -> f32 {
228 match self.as_rgba() {
229 Color::Rgba { green, .. } => green,
230 }
231 }
232
233 pub fn b(&self) -> f32 {
235 match self.as_rgba() {
236 Color::Rgba { blue, .. } => blue,
237 }
238 }
239
240 pub fn set_r(&mut self, r: f32) -> &mut Self {
242 *self = self.as_rgba();
243 match self {
244 Color::Rgba { red, .. } => *red = r,
245 }
246 self
247 }
248
249 pub fn set_g(&mut self, g: f32) -> &mut Self {
251 *self = self.as_rgba();
252 match self {
253 Color::Rgba { green, .. } => *green = g,
254 }
255 self
256 }
257
258 pub fn set_b(&mut self, b: f32) -> &mut Self {
260 *self = self.as_rgba();
261 match self {
262 Color::Rgba { blue, .. } => *blue = b,
263 }
264 self
265 }
266
267 #[inline(always)]
269 pub fn a(&self) -> f32 {
270 match self {
271 Color::Rgba { alpha, .. } => *alpha,
272 }
273 }
274
275 pub fn set_a(&mut self, a: f32) -> &mut Self {
277 match self {
278 Color::Rgba { alpha, .. } => {
279 *alpha = a;
280 }
281 }
282 self
283 }
284
285 pub fn as_rgba(self: &Color) -> Color {
287 match self {
288 Color::Rgba { .. } => *self,
289 }
290 }
291
292 pub fn as_rgba_f32(self: Color) -> [f32; 4] {
294 match self {
295 Color::Rgba {
296 red,
297 green,
298 blue,
299 alpha,
300 } => [red, green, blue, alpha],
301 }
302 }
303}
304
305impl Default for Color {
306 fn default() -> Self {
307 Color::WHITE
308 }
309}
310
311impl AddAssign<Color> for Color {
312 fn add_assign(&mut self, rhs: Color) {
313 match self {
314 Color::Rgba {
315 red,
316 green,
317 blue,
318 alpha,
319 } => {
320 let rhs = rhs.as_rgba_f32();
321 *red += rhs[0];
322 *green += rhs[1];
323 *blue += rhs[2];
324 *alpha += rhs[3];
325 }
326 }
327 }
328}
329
330impl Add<Color> for Color {
331 type Output = Color;
332
333 fn add(self, rhs: Color) -> Self::Output {
334 match self {
335 Color::Rgba {
336 red,
337 green,
338 blue,
339 alpha,
340 } => {
341 let rhs = rhs.as_rgba_f32();
342 Color::Rgba {
343 red: red + rhs[0],
344 green: green + rhs[1],
345 blue: blue + rhs[2],
346 alpha: alpha + rhs[3],
347 }
348 }
349 }
350 }
351}
352
353impl From<Color> for [f32; 4] {
354 fn from(color: Color) -> Self {
355 color.as_rgba_f32()
356 }
357}
358
359impl From<[f32; 4]> for Color {
360 fn from([r, g, b, a]: [f32; 4]) -> Self {
361 Color::rgba(r, g, b, a)
362 }
363}
364
365impl From<[f32; 3]> for Color {
366 fn from([r, g, b]: [f32; 3]) -> Self {
367 Color::rgb(r, g, b)
368 }
369}
370
371impl From<Color> for Vec4 {
372 fn from(color: Color) -> Self {
373 let color: [f32; 4] = color.into();
374 Vec4::new(color[0], color[1], color[2], color[3])
375 }
376}
377
378impl From<Vec4> for Color {
379 fn from(vec4: Vec4) -> Self {
380 Color::rgba(vec4.x, vec4.y, vec4.z, vec4.w)
381 }
382}
383
384impl Mul<f32> for Color {
385 type Output = Color;
386
387 fn mul(self, rhs: f32) -> Self::Output {
388 match self {
389 Color::Rgba {
390 red,
391 green,
392 blue,
393 alpha,
394 } => Color::Rgba {
395 red: red * rhs,
396 green: green * rhs,
397 blue: blue * rhs,
398 alpha,
399 },
400 }
401 }
402}
403
404impl MulAssign<f32> for Color {
405 fn mul_assign(&mut self, rhs: f32) {
406 match self {
407 Color::Rgba {
408 red, green, blue, ..
409 } => {
410 *red *= rhs;
411 *green *= rhs;
412 *blue *= rhs;
413 }
414 }
415 }
416}
417
418impl Mul<Vec4> for Color {
419 type Output = Color;
420
421 fn mul(self, rhs: Vec4) -> Self::Output {
422 match self {
423 Color::Rgba {
424 red,
425 green,
426 blue,
427 alpha,
428 } => Color::Rgba {
429 red: red * rhs.x,
430 green: green * rhs.y,
431 blue: blue * rhs.z,
432 alpha: alpha * rhs.w,
433 },
434 }
435 }
436}
437
438impl MulAssign<Vec4> for Color {
439 fn mul_assign(&mut self, rhs: Vec4) {
440 match self {
441 Color::Rgba {
442 red,
443 green,
444 blue,
445 alpha,
446 } => {
447 *red *= rhs.x;
448 *green *= rhs.y;
449 *blue *= rhs.z;
450 *alpha *= rhs.w;
451 }
452 }
453 }
454}
455
456impl Mul<Vec3> for Color {
457 type Output = Color;
458
459 fn mul(self, rhs: Vec3) -> Self::Output {
460 match self {
461 Color::Rgba {
462 red,
463 green,
464 blue,
465 alpha,
466 } => Color::Rgba {
467 red: red * rhs.x,
468 green: green * rhs.y,
469 blue: blue * rhs.z,
470 alpha,
471 },
472 }
473 }
474}
475
476impl MulAssign<Vec3> for Color {
477 fn mul_assign(&mut self, rhs: Vec3) {
478 match self {
479 Color::Rgba {
480 red, green, blue, ..
481 } => {
482 *red *= rhs.x;
483 *green *= rhs.y;
484 *blue *= rhs.z;
485 }
486 }
487 }
488}
489
490impl Mul<[f32; 4]> for Color {
491 type Output = Color;
492
493 fn mul(self, rhs: [f32; 4]) -> Self::Output {
494 match self {
495 Color::Rgba {
496 red,
497 green,
498 blue,
499 alpha,
500 } => Color::Rgba {
501 red: red * rhs[0],
502 green: green * rhs[1],
503 blue: blue * rhs[2],
504 alpha: alpha * rhs[3],
505 },
506 }
507 }
508}
509
510impl MulAssign<[f32; 4]> for Color {
511 fn mul_assign(&mut self, rhs: [f32; 4]) {
512 match self {
513 Color::Rgba {
514 red,
515 green,
516 blue,
517 alpha,
518 } => {
519 *red *= rhs[0];
520 *green *= rhs[1];
521 *blue *= rhs[2];
522 *alpha *= rhs[3];
523 }
524 }
525 }
526}
527
528impl Mul<[f32; 3]> for Color {
529 type Output = Color;
530
531 fn mul(self, rhs: [f32; 3]) -> Self::Output {
532 match self {
533 Color::Rgba {
534 red,
535 green,
536 blue,
537 alpha,
538 } => Color::Rgba {
539 red: red * rhs[0],
540 green: green * rhs[1],
541 blue: blue * rhs[2],
542 alpha,
543 },
544 }
545 }
546}
547
548impl MulAssign<[f32; 3]> for Color {
549 fn mul_assign(&mut self, rhs: [f32; 3]) {
550 match self {
551 Color::Rgba {
552 red, green, blue, ..
553 } => {
554 *red *= rhs[0];
555 *green *= rhs[1];
556 *blue *= rhs[2];
557 }
558 }
559 }
560}
561
562#[derive(Debug, Error)]
564pub enum HexColorError {
565 #[error("Unexpected length of hex string")]
567 Length,
568 #[error("Error parsing hex value")]
570 Hex(#[from] hex::FromHexError),
571}
572
573fn decode_rgb(data: &[u8]) -> Result<Color, HexColorError> {
574 let mut buf = [0; 3];
575 match hex::decode_to_slice(data, &mut buf) {
576 Ok(_) => {
577 let r = buf[0] as f32 / 255.0;
578 let g = buf[1] as f32 / 255.0;
579 let b = buf[2] as f32 / 255.0;
580 Ok(Color::rgb(r, g, b))
581 }
582 Err(err) => Err(HexColorError::Hex(err)),
583 }
584}
585
586fn decode_rgba(data: &[u8]) -> Result<Color, HexColorError> {
587 let mut buf = [0; 4];
588 match hex::decode_to_slice(data, &mut buf) {
589 Ok(_) => {
590 let r = buf[0] as f32 / 255.0;
591 let g = buf[1] as f32 / 255.0;
592 let b = buf[2] as f32 / 255.0;
593 let a = buf[3] as f32 / 255.0;
594 Ok(Color::rgba(r, g, b, a))
595 }
596 Err(err) => Err(HexColorError::Hex(err)),
597 }
598}