Add Saturation trait to bevy_color (#18202)
# Objective - Allow for convenient access and mutation of color saturation providing following the `Hue`, `Luminance` traits. - `with_saturation()` builder method - `saturation()` to get the saturation of a `Color` - `set_saturation()` to set the saturation of a mutable `Color` ## Solution - Defined `Saturation` trait in `color_ops.rs` - Implemented `Saturation` on `Hsla` and `Hsva` - Implemented `Saturation` on `Color` which proxies to other color space impls. - In the case of colorspaces which don't have native saturation components the color is converted to 'Hsla` internally ## Testing - Empirically tested --- ## Showcase ```rust fn next_golden(&mut self) -> Color { self.current .rotate_hue((1.0 / GOLDEN_RATIO) * 360.0) .with_saturation(self.rand_saturation()) .with_luminance(self.rand_luminance()) .into() } ``` --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
parent
65a9e6fd9f
commit
4e2dc4b15f
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
color_difference::EuclideanDistance, Alpha, Hsla, Hsva, Hue, Hwba, Laba, Lcha, LinearRgba,
|
||||
Luminance, Mix, Oklaba, Oklcha, Srgba, StandardColor, Xyza,
|
||||
Luminance, Mix, Oklaba, Oklcha, Saturation, Srgba, StandardColor, Xyza,
|
||||
};
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
use bevy_reflect::prelude::*;
|
||||
@ -810,6 +810,44 @@ impl Hue for Color {
|
||||
}
|
||||
}
|
||||
|
||||
impl Saturation for Color {
|
||||
fn with_saturation(&self, saturation: f32) -> Self {
|
||||
let mut new = *self;
|
||||
|
||||
match &mut new {
|
||||
Color::Srgba(x) => Hsla::from(*x).with_saturation(saturation).into(),
|
||||
Color::LinearRgba(x) => Hsla::from(*x).with_saturation(saturation).into(),
|
||||
Color::Hsla(x) => x.with_saturation(saturation).into(),
|
||||
Color::Hsva(x) => x.with_saturation(saturation).into(),
|
||||
Color::Hwba(x) => Hsla::from(*x).with_saturation(saturation).into(),
|
||||
Color::Laba(x) => Hsla::from(*x).with_saturation(saturation).into(),
|
||||
Color::Lcha(x) => Hsla::from(*x).with_saturation(saturation).into(),
|
||||
Color::Oklaba(x) => Hsla::from(*x).with_saturation(saturation).into(),
|
||||
Color::Oklcha(x) => Hsla::from(*x).with_saturation(saturation).into(),
|
||||
Color::Xyza(x) => Hsla::from(*x).with_saturation(saturation).into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn saturation(&self) -> f32 {
|
||||
match self {
|
||||
Color::Srgba(x) => Hsla::from(*x).saturation(),
|
||||
Color::LinearRgba(x) => Hsla::from(*x).saturation(),
|
||||
Color::Hsla(x) => x.saturation(),
|
||||
Color::Hsva(x) => x.saturation(),
|
||||
Color::Hwba(x) => Hsla::from(*x).saturation(),
|
||||
Color::Laba(x) => Hsla::from(*x).saturation(),
|
||||
Color::Lcha(x) => Hsla::from(*x).saturation(),
|
||||
Color::Oklaba(x) => Hsla::from(*x).saturation(),
|
||||
Color::Oklcha(x) => Hsla::from(*x).saturation(),
|
||||
Color::Xyza(x) => Hsla::from(*x).saturation(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_saturation(&mut self, saturation: f32) {
|
||||
*self = self.with_saturation(saturation);
|
||||
}
|
||||
}
|
||||
|
||||
impl Mix for Color {
|
||||
fn mix(&self, other: &Self, factor: f32) -> Self {
|
||||
let mut new = *self;
|
||||
|
@ -95,6 +95,21 @@ pub trait Hue: Sized {
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for manipulating the saturation of a color.
|
||||
///
|
||||
/// When working with color spaces that do not have native saturation components
|
||||
/// the operations are performed in [`crate::Hsla`].
|
||||
pub trait Saturation: Sized {
|
||||
/// Return a new version of this color with the saturation channel set to the given value.
|
||||
fn with_saturation(&self, saturation: f32) -> Self;
|
||||
|
||||
/// Return the saturation of this color [0.0, 1.0].
|
||||
fn saturation(&self) -> f32;
|
||||
|
||||
/// Sets the saturation of this color.
|
||||
fn set_saturation(&mut self, saturation: f32);
|
||||
}
|
||||
|
||||
/// Trait with methods for converting colors to non-color types
|
||||
pub trait ColorToComponents {
|
||||
/// Convert to an f32 array
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
Alpha, ColorToComponents, Gray, Hsva, Hue, Hwba, Lcha, LinearRgba, Luminance, Mix, Srgba,
|
||||
StandardColor, Xyza,
|
||||
Alpha, ColorToComponents, Gray, Hsva, Hue, Hwba, Lcha, LinearRgba, Luminance, Mix, Saturation,
|
||||
Srgba, StandardColor, Xyza,
|
||||
};
|
||||
use bevy_math::{Vec3, Vec4};
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
@ -159,6 +159,26 @@ impl Hue for Hsla {
|
||||
}
|
||||
}
|
||||
|
||||
impl Saturation for Hsla {
|
||||
#[inline]
|
||||
fn with_saturation(&self, saturation: f32) -> Self {
|
||||
Self {
|
||||
saturation,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn saturation(&self) -> f32 {
|
||||
self.saturation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_saturation(&mut self, saturation: f32) {
|
||||
self.saturation = saturation;
|
||||
}
|
||||
}
|
||||
|
||||
impl Luminance for Hsla {
|
||||
#[inline]
|
||||
fn with_luminance(&self, lightness: f32) -> Self {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::{
|
||||
Alpha, ColorToComponents, Gray, Hue, Hwba, Lcha, LinearRgba, Mix, Srgba, StandardColor, Xyza,
|
||||
Alpha, ColorToComponents, Gray, Hue, Hwba, Lcha, LinearRgba, Mix, Saturation, Srgba,
|
||||
StandardColor, Xyza,
|
||||
};
|
||||
use bevy_math::{Vec3, Vec4};
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
@ -129,6 +130,26 @@ impl Hue for Hsva {
|
||||
}
|
||||
}
|
||||
|
||||
impl Saturation for Hsva {
|
||||
#[inline]
|
||||
fn with_saturation(&self, saturation: f32) -> Self {
|
||||
Self {
|
||||
saturation,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn saturation(&self) -> f32 {
|
||||
self.saturation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_saturation(&mut self, saturation: f32) {
|
||||
self.saturation = saturation;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Hsva> for Hwba {
|
||||
fn from(
|
||||
Hsva {
|
||||
|
Loading…
Reference in New Issue
Block a user