Skip to content

Commit

Permalink
bevy_color: Created a private trait StandardColor (bevyengine#12072)
Browse files Browse the repository at this point in the history
# Objective

- Assist Bevy contributors in the creation of `bevy_color` spaces by
ensuring consistent API implementation.

## Solution

Created a `pub(crate)` trait `StandardColor` which has all the
requirements for a typical color space (e.g, `Srgba`, `Color`, etc.).

---

## Changelog

- Implemented traits missing from certain color spaces.

## Migration Guide

_No migration required_
  • Loading branch information
bushrat011899 authored and msvbg committed Feb 26, 2024
1 parent 092daaa commit 313565f
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 12 deletions.
59 changes: 57 additions & 2 deletions crates/bevy_color/src/color.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use crate::{Hsla, Lcha, LinearRgba, Oklaba, Srgba};
use crate::{Alpha, Hsla, Lcha, LinearRgba, Oklaba, Srgba, StandardColor};
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use bevy_render::color::Color as LegacyColor;
use serde::{Deserialize, Serialize};

/// An enumerated type that can represent any of the color types in this crate.
///
/// This is useful when you need to store a color in a data structure that can't be generic over
/// the color type.
#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
pub enum Color {
/// A color in the sRGB color space with alpha.
Srgba(Srgba),
Expand All @@ -18,6 +22,8 @@ pub enum Color {
Oklaba(Oklaba),
}

impl StandardColor for Color {}

impl Color {
/// Return the color as a linear RGBA color.
pub fn linear(&self) -> LinearRgba {
Expand All @@ -37,6 +43,32 @@ impl Default for Color {
}
}

impl Alpha for Color {
fn with_alpha(&self, alpha: f32) -> Self {
let mut new = *self;

match &mut new {
Color::Srgba(x) => *x = x.with_alpha(alpha),
Color::LinearRgba(x) => *x = x.with_alpha(alpha),
Color::Hsla(x) => *x = x.with_alpha(alpha),
Color::Lcha(x) => *x = x.with_alpha(alpha),
Color::Oklaba(x) => *x = x.with_alpha(alpha),
}

new
}

fn alpha(&self) -> f32 {
match self {
Color::Srgba(x) => x.alpha(),
Color::LinearRgba(x) => x.alpha(),
Color::Hsla(x) => x.alpha(),
Color::Lcha(x) => x.alpha(),
Color::Oklaba(x) => x.alpha(),
}
}
}

impl From<Srgba> for Color {
fn from(value: Srgba) -> Self {
Self::Srgba(value)
Expand Down Expand Up @@ -126,3 +158,26 @@ impl From<Color> for Oklaba {
}
}
}

impl From<LegacyColor> for Color {
fn from(value: LegacyColor) -> Self {
match value {
LegacyColor::Rgba { .. } => Srgba::from(value).into(),
LegacyColor::RgbaLinear { .. } => LinearRgba::from(value).into(),
LegacyColor::Hsla { .. } => Hsla::from(value).into(),
LegacyColor::Lcha { .. } => Lcha::from(value).into(),
}
}
}

impl From<Color> for LegacyColor {
fn from(value: Color) -> Self {
match value {
Color::Srgba(x) => x.into(),
Color::LinearRgba(x) => x.into(),
Color::Hsla(x) => x.into(),
Color::Lcha(x) => x.into(),
Color::Oklaba(x) => x.into(),
}
}
}
28 changes: 21 additions & 7 deletions crates/bevy_color/src/hsla.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Alpha, LinearRgba, Luminance, Mix, Srgba};
use crate::{Alpha, Lcha, LinearRgba, Luminance, Mix, Oklaba, Srgba, StandardColor};
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use bevy_render::color::HslRepresentation;
use serde::{Deserialize, Serialize};
Expand All @@ -17,6 +17,8 @@ pub struct Hsla {
pub alpha: f32,
}

impl StandardColor for Hsla {}

impl Hsla {
/// Construct a new [`Hsla`] color from components.
///
Expand Down Expand Up @@ -119,12 +121,6 @@ impl From<Srgba> for Hsla {
}
}

impl From<LinearRgba> for Hsla {
fn from(value: LinearRgba) -> Self {
Hsla::from(Srgba::from(value))
}
}

impl From<Hsla> for bevy_render::color::Color {
fn from(value: Hsla) -> Self {
bevy_render::color::Color::Hsla {
Expand All @@ -150,6 +146,24 @@ impl From<bevy_render::color::Color> for Hsla {
}
}

impl From<LinearRgba> for Hsla {
fn from(value: LinearRgba) -> Self {
Srgba::from(value).into()
}
}

impl From<Oklaba> for Hsla {
fn from(value: Oklaba) -> Self {
Srgba::from(value).into()
}
}

impl From<Lcha> for Hsla {
fn from(value: Lcha) -> Self {
Srgba::from(value).into()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
16 changes: 15 additions & 1 deletion crates/bevy_color/src/lcha.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Alpha, LinearRgba, Luminance, Mix, Srgba};
use crate::{Alpha, Hsla, LinearRgba, Luminance, Mix, Oklaba, Srgba, StandardColor};
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use bevy_render::color::LchRepresentation;
use serde::{Deserialize, Serialize};
Expand All @@ -17,6 +17,8 @@ pub struct Lcha {
pub alpha: f32,
}

impl StandardColor for Lcha {}

impl Lcha {
/// Construct a new [`Lcha`] color from components.
///
Expand Down Expand Up @@ -165,6 +167,18 @@ impl From<bevy_render::color::Color> for Lcha {
}
}

impl From<Oklaba> for Lcha {
fn from(value: Oklaba) -> Self {
Srgba::from(value).into()
}
}

impl From<Hsla> for Lcha {
fn from(value: Hsla) -> Self {
Srgba::from(value).into()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
22 changes: 22 additions & 0 deletions crates/bevy_color/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,25 @@ pub use lcha::*;
pub use linear_rgba::*;
pub use oklaba::*;
pub use srgba::*;

use bevy_render::color::Color as LegacyColor;

/// Describes the traits that a color should implement for consistency.
pub(crate) trait StandardColor
where
Self: core::fmt::Debug,
Self: Clone + Copy,
Self: PartialEq,
Self: serde::Serialize + for<'a> serde::Deserialize<'a>,
Self: bevy_reflect::Reflect,
Self: Default,
Self: From<Color> + Into<Color>,
Self: From<LegacyColor> + Into<LegacyColor>,
Self: From<Srgba> + Into<Srgba>,
Self: From<LinearRgba> + Into<LinearRgba>,
Self: From<Hsla> + Into<Hsla>,
Self: From<Lcha> + Into<Lcha>,
Self: From<Oklaba> + Into<Oklaba>,
Self: Alpha,
{
}
3 changes: 3 additions & 0 deletions crates/bevy_color/src/linear_rgba.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
color_difference::EuclideanDistance, oklaba::Oklaba, Alpha, Hsla, Luminance, Mix, Srgba,
StandardColor,
};
use bevy_math::Vec4;
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
Expand All @@ -20,6 +21,8 @@ pub struct LinearRgba {
pub alpha: f32,
}

impl StandardColor for LinearRgba {}

impl LinearRgba {
/// Construct a new [`LinearRgba`] color from components.
pub const fn new(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
Expand Down
32 changes: 31 additions & 1 deletion crates/bevy_color/src/oklaba.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use crate::{color_difference::EuclideanDistance, Alpha, LinearRgba, Luminance, Mix, Srgba};
use crate::{
color_difference::EuclideanDistance, Alpha, Hsla, Lcha, LinearRgba, Luminance, Mix, Srgba,
StandardColor,
};
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use bevy_render::color::Color as LegacyColor;
use serde::{Deserialize, Serialize};

/// Color in Oklaba color space, with alpha
Expand All @@ -16,6 +20,8 @@ pub struct Oklaba {
pub alpha: f32,
}

impl StandardColor for Oklaba {}

impl Oklaba {
/// Construct a new [`Oklaba`] color from components.
///
Expand Down Expand Up @@ -132,6 +138,30 @@ impl From<Srgba> for Oklaba {
}
}

impl From<Lcha> for Oklaba {
fn from(value: Lcha) -> Self {
LinearRgba::from(value).into()
}
}

impl From<Hsla> for Oklaba {
fn from(value: Hsla) -> Self {
LinearRgba::from(value).into()
}
}

impl From<LegacyColor> for Oklaba {
fn from(value: LegacyColor) -> Self {
LinearRgba::from(value).into()
}
}

impl From<Oklaba> for LegacyColor {
fn from(value: Oklaba) -> Self {
LinearRgba::from(value).into()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_color/src/srgba.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::color_difference::EuclideanDistance;
use crate::oklaba::Oklaba;
use crate::{Alpha, Hsla, LinearRgba, Luminance, Mix};
use crate::{Alpha, Hsla, LinearRgba, Luminance, Mix, StandardColor};
use bevy_math::Vec4;
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use bevy_render::color::{HexColorError, HslRepresentation, SrgbColorSpace};
Expand All @@ -20,6 +20,8 @@ pub struct Srgba {
pub alpha: f32,
}

impl StandardColor for Srgba {}

impl Srgba {
// The standard VGA colors, with alpha set to 1.0.
// https://en.wikipedia.org/wiki/Web_colors#Basic_colors
Expand Down

0 comments on commit 313565f

Please sign in to comment.