mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 22:20:20 +00:00
Explicit color conversion methods (#10321)
# Objective Closes #10319 ## Changelog * Added a new `Color::rgba_from_array([f32; 4]) -> Color` method. * Added a new `Color::rgb_from_array([f32; 3]) -> Color` method. * Added a new `Color::rgba_linear_from_array([f32; 4]) -> Color` method. * Added a new `Color::rgb_linear_from_array([f32; 3]) -> Color` method. * Added a new `Color::hsla_from_array([f32; 4]) -> Color` method. * Added a new `Color::hsl_from_array([f32; 3]) -> Color` method. * Added a new `Color::lcha_from_array([f32; 4]) -> Color` method. * Added a new `Color::lch_from_array([f32; 3]) -> Color` method. * Added a new `Color::rgba_to_vec4(&self) -> Vec4` method. * Added a new `Color::rgba_to_array(&self) -> [f32; 4]` method. * Added a new `Color::rgb_to_vec3(&self) -> Vec3` method. * Added a new `Color::rgb_to_array(&self) -> [f32; 3]` method. * Added a new `Color::rgba_linear_to_vec4(&self) -> Vec4` method. * Added a new `Color::rgba_linear_to_array(&self) -> [f32; 4]` method. * Added a new `Color::rgb_linear_to_vec3(&self) -> Vec3` method. * Added a new `Color::rgb_linear_to_array(&self) -> [f32; 3]` method. * Added a new `Color::hsla_to_vec4(&self) -> Vec4` method. * Added a new `Color::hsla_to_array(&self) -> [f32; 4]` method. * Added a new `Color::hsl_to_vec3(&self) -> Vec3` method. * Added a new `Color::hsl_to_array(&self) -> [f32; 3]` method. * Added a new `Color::lcha_to_vec4(&self) -> Vec4` method. * Added a new `Color::lcha_to_array(&self) -> [f32; 4]` method. * Added a new `Color::lch_to_vec3(&self) -> Vec3` method. * Added a new `Color::lch_to_array(&self) -> [f32; 3]` method. ## Migration Guide `Color::from(Vec4)` is now `Color::rgba_from_array(impl Into<[f32; 4]>)` `Vec4::from(Color)` is now `Color::rgba_to_vec4(&self)` Before: ```rust let color_vec4 = Vec4::new(0.5, 0.5, 0.5); let color_from_vec4 = Color::from(color_vec4); let color_array = [0.5, 0.5, 0.5]; let color_from_array = Color::from(color_array); ``` After: ```rust let color_vec4 = Vec4::new(0.5, 0.5, 0.5); let color_from_vec4 = Color::rgba_from_array(color_vec4); let color_array = [0.5, 0.5, 0.5]; let color_from_array = Color::rgba_from_array(color_array); ```
This commit is contained in:
parent
dcfae72386
commit
cbcd826612
3 changed files with 160 additions and 93 deletions
|
@ -998,7 +998,7 @@ fn load_node(
|
|||
gltf::khr_lights_punctual::Kind::Directional => {
|
||||
let mut entity = parent.spawn(DirectionalLightBundle {
|
||||
directional_light: DirectionalLight {
|
||||
color: Color::from(light.color()),
|
||||
color: Color::rgb_from_array(light.color()),
|
||||
// NOTE: KHR_punctual_lights defines the intensity units for directional
|
||||
// lights in lux (lm/m^2) which is what we need.
|
||||
illuminance: light.intensity(),
|
||||
|
@ -1018,7 +1018,7 @@ fn load_node(
|
|||
gltf::khr_lights_punctual::Kind::Point => {
|
||||
let mut entity = parent.spawn(PointLightBundle {
|
||||
point_light: PointLight {
|
||||
color: Color::from(light.color()),
|
||||
color: Color::rgb_from_array(light.color()),
|
||||
// NOTE: KHR_punctual_lights defines the intensity units for point lights in
|
||||
// candela (lm/sr) which is luminous intensity and we need luminous power.
|
||||
// For a point light, luminous power = 4 * pi * luminous intensity
|
||||
|
@ -1044,7 +1044,7 @@ fn load_node(
|
|||
} => {
|
||||
let mut entity = parent.spawn(SpotLightBundle {
|
||||
spot_light: SpotLight {
|
||||
color: Color::from(light.color()),
|
||||
color: Color::rgb_from_array(light.color()),
|
||||
// NOTE: KHR_punctual_lights defines the intensity units for spot lights in
|
||||
// candela (lm/sr) which is luminous intensity and we need luminous power.
|
||||
// For a spot light, we map luminous power = 4 * pi * luminous intensity
|
||||
|
|
|
@ -5,7 +5,7 @@ pub use colorspace::*;
|
|||
use bevy_math::{Vec3, Vec4};
|
||||
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::{Add, AddAssign, Mul, MulAssign};
|
||||
use std::ops::{Add, Mul, MulAssign};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
|
||||
|
@ -1102,67 +1102,182 @@ impl Color {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Color {
|
||||
fn default() -> Self {
|
||||
Color::WHITE
|
||||
/// New `Color` from `[f32; 4]` (or a type that can be converted into them) with RGB representation in sRGB colorspace.
|
||||
#[inline]
|
||||
pub fn rgba_from_array(arr: impl Into<[f32; 4]>) -> Self {
|
||||
let [r, g, b, a]: [f32; 4] = arr.into();
|
||||
Color::rgba(r, g, b, a)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Color> for Color {
|
||||
fn add_assign(&mut self, rhs: Color) {
|
||||
match self {
|
||||
/// New `Color` from `[f32; 3]` (or a type that can be converted into them) with RGB representation in sRGB colorspace.
|
||||
#[inline]
|
||||
pub fn rgb_from_array(arr: impl Into<[f32; 3]>) -> Self {
|
||||
let [r, g, b]: [f32; 3] = arr.into();
|
||||
Color::rgb(r, g, b)
|
||||
}
|
||||
|
||||
/// New `Color` from `[f32; 4]` (or a type that can be converted into them) with RGB representation in linear RGB colorspace.
|
||||
#[inline]
|
||||
pub fn rgba_linear_from_array(arr: impl Into<[f32; 4]>) -> Self {
|
||||
let [r, g, b, a]: [f32; 4] = arr.into();
|
||||
Color::rgba_linear(r, g, b, a)
|
||||
}
|
||||
|
||||
/// New `Color` from `[f32; 3]` (or a type that can be converted into them) with RGB representation in linear RGB colorspace.
|
||||
#[inline]
|
||||
pub fn rgb_linear_from_array(arr: impl Into<[f32; 3]>) -> Self {
|
||||
let [r, g, b]: [f32; 3] = arr.into();
|
||||
Color::rgb_linear(r, g, b)
|
||||
}
|
||||
|
||||
/// New `Color` from `[f32; 4]` (or a type that can be converted into them) with HSL representation in sRGB colorspace.
|
||||
#[inline]
|
||||
pub fn hsla_from_array(arr: impl Into<[f32; 4]>) -> Self {
|
||||
let [h, s, l, a]: [f32; 4] = arr.into();
|
||||
Color::hsla(h, s, l, a)
|
||||
}
|
||||
|
||||
/// New `Color` from `[f32; 3]` (or a type that can be converted into them) with HSL representation in sRGB colorspace.
|
||||
#[inline]
|
||||
pub fn hsl_from_array(arr: impl Into<[f32; 3]>) -> Self {
|
||||
let [h, s, l]: [f32; 3] = arr.into();
|
||||
Color::hsl(h, s, l)
|
||||
}
|
||||
|
||||
/// New `Color` from `[f32; 4]` (or a type that can be converted into them) with LCH representation in sRGB colorspace.
|
||||
#[inline]
|
||||
pub fn lcha_from_array(arr: impl Into<[f32; 4]>) -> Self {
|
||||
let [l, c, h, a]: [f32; 4] = arr.into();
|
||||
Color::lcha(l, c, h, a)
|
||||
}
|
||||
|
||||
/// New `Color` from `[f32; 3]` (or a type that can be converted into them) with LCH representation in sRGB colorspace.
|
||||
#[inline]
|
||||
pub fn lch_from_array(arr: impl Into<[f32; 3]>) -> Self {
|
||||
let [l, c, h]: [f32; 3] = arr.into();
|
||||
Color::lch(l, c, h)
|
||||
}
|
||||
|
||||
/// Convert `Color` to RGBA and return as `Vec4`.
|
||||
#[inline]
|
||||
pub fn rgba_to_vec4(&self) -> Vec4 {
|
||||
let color = self.as_rgba();
|
||||
match color {
|
||||
Color::Rgba {
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
alpha,
|
||||
} => {
|
||||
let rhs = rhs.as_rgba_f32();
|
||||
*red += rhs[0];
|
||||
*green += rhs[1];
|
||||
*blue += rhs[2];
|
||||
*alpha += rhs[3];
|
||||
}
|
||||
} => Vec4::new(red, green, blue, alpha),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert `Color` to RGBA and return as `Vec3`.
|
||||
#[inline]
|
||||
pub fn rgb_to_vec3(&self) -> Vec3 {
|
||||
let color = self.as_rgba();
|
||||
match color {
|
||||
Color::Rgba {
|
||||
red, green, blue, ..
|
||||
} => Vec3::new(red, green, blue),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert `Color` to linear RGBA and return as `Vec4`.
|
||||
#[inline]
|
||||
pub fn rgba_linear_to_vec4(&self) -> Vec4 {
|
||||
let color = self.as_rgba_linear();
|
||||
match color {
|
||||
Color::RgbaLinear {
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
alpha,
|
||||
} => {
|
||||
let rhs = rhs.as_linear_rgba_f32();
|
||||
*red += rhs[0];
|
||||
*green += rhs[1];
|
||||
*blue += rhs[2];
|
||||
*alpha += rhs[3];
|
||||
}
|
||||
} => Vec4::new(red, green, blue, alpha),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert `Color` to linear RGBA and return as `Vec3`.
|
||||
#[inline]
|
||||
pub fn rgb_linear_to_vec3(&self) -> Vec3 {
|
||||
let color = self.as_rgba_linear();
|
||||
match color {
|
||||
Color::RgbaLinear {
|
||||
red, green, blue, ..
|
||||
} => Vec3::new(red, green, blue),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert `Color` to HSLA and return as `Vec4`.
|
||||
#[inline]
|
||||
pub fn hsla_to_vec4(&self) -> Vec4 {
|
||||
let color = self.as_hsla();
|
||||
match color {
|
||||
Color::Hsla {
|
||||
hue,
|
||||
saturation,
|
||||
lightness,
|
||||
alpha,
|
||||
} => {
|
||||
let rhs = rhs.as_hsla_f32();
|
||||
*hue += rhs[0];
|
||||
*saturation += rhs[1];
|
||||
*lightness += rhs[2];
|
||||
*alpha += rhs[3];
|
||||
}
|
||||
} => Vec4::new(hue, saturation, lightness, alpha),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert `Color` to HSLA and return as `Vec3`.
|
||||
#[inline]
|
||||
pub fn hsl_to_vec3(&self) -> Vec3 {
|
||||
let color = self.as_hsla();
|
||||
match color {
|
||||
Color::Hsla {
|
||||
hue,
|
||||
saturation,
|
||||
lightness,
|
||||
..
|
||||
} => Vec3::new(hue, saturation, lightness),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert `Color` to LCHA and return as `Vec4`.
|
||||
#[inline]
|
||||
pub fn lcha_to_vec4(&self) -> Vec4 {
|
||||
let color = self.as_lcha();
|
||||
match color {
|
||||
Color::Lcha {
|
||||
lightness,
|
||||
chroma,
|
||||
hue,
|
||||
alpha,
|
||||
} => {
|
||||
let rhs = rhs.as_lcha_f32();
|
||||
*lightness += rhs[0];
|
||||
*chroma += rhs[1];
|
||||
*hue += rhs[2];
|
||||
*alpha += rhs[3];
|
||||
}
|
||||
} => Vec4::new(lightness, chroma, hue, alpha),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert `Color` to LCHA and return as `Vec3`.
|
||||
#[inline]
|
||||
pub fn lch_to_vec3(&self) -> Vec3 {
|
||||
let color = self.as_lcha();
|
||||
match color {
|
||||
Color::Lcha {
|
||||
lightness,
|
||||
chroma,
|
||||
hue,
|
||||
..
|
||||
} => Vec3::new(lightness, chroma, hue),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Color {
|
||||
fn default() -> Self {
|
||||
Color::WHITE
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Color> for Color {
|
||||
|
@ -1219,7 +1334,6 @@ impl Add<Color> for Color {
|
|||
alpha,
|
||||
} => {
|
||||
let rhs = rhs.as_lcha_f32();
|
||||
|
||||
Color::Lcha {
|
||||
lightness: lightness + rhs[0],
|
||||
chroma: chroma + rhs[1],
|
||||
|
@ -1231,53 +1345,6 @@ impl Add<Color> for Color {
|
|||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Vec4> for Color {
|
||||
fn add_assign(&mut self, rhs: Vec4) {
|
||||
let rhs: Color = rhs.into();
|
||||
*self += rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Vec4> for Color {
|
||||
type Output = Color;
|
||||
|
||||
fn add(self, rhs: Vec4) -> Self::Output {
|
||||
let rhs: Color = rhs.into();
|
||||
self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for [f32; 4] {
|
||||
fn from(color: Color) -> Self {
|
||||
color.as_rgba_f32()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 4]> for Color {
|
||||
fn from([r, g, b, a]: [f32; 4]) -> Self {
|
||||
Color::rgba(r, g, b, a)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 3]> for Color {
|
||||
fn from([r, g, b]: [f32; 3]) -> Self {
|
||||
Color::rgb(r, g, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for Vec4 {
|
||||
fn from(color: Color) -> Self {
|
||||
let color: [f32; 4] = color.into();
|
||||
Vec4::new(color[0], color[1], color[2], color[3])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec4> for Color {
|
||||
fn from(vec4: Vec4) -> Self {
|
||||
Color::rgba(vec4.x, vec4.y, vec4.z, vec4.w)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for wgpu::Color {
|
||||
fn from(color: Color) -> Self {
|
||||
if let Color::RgbaLinear {
|
||||
|
@ -1909,15 +1976,15 @@ mod tests {
|
|||
#[test]
|
||||
fn conversions_vec4() {
|
||||
let starting_vec4 = Vec4::new(0.4, 0.5, 0.6, 1.0);
|
||||
let starting_color = Color::from(starting_vec4);
|
||||
let starting_color = Color::rgba_from_array(starting_vec4);
|
||||
|
||||
assert_eq!(starting_vec4, Vec4::from(starting_color));
|
||||
assert_eq!(starting_vec4, starting_color.rgba_to_vec4());
|
||||
|
||||
let transformation = Vec4::new(0.5, 0.5, 0.5, 1.0);
|
||||
|
||||
assert_eq!(
|
||||
starting_color * transformation,
|
||||
Color::from(starting_vec4 * transformation),
|
||||
Color::rgba_from_array(starting_vec4 * transformation)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ fn update(time: Res<Time>, mut ui_materials: ResMut<Assets<CustomUiMaterial>>) {
|
|||
for (_, material) in ui_materials.iter_mut() {
|
||||
// rainbow color effect
|
||||
let new_color = Color::hsl((time.elapsed_seconds() * 60.0) % 360.0, 1., 0.5);
|
||||
material.color = new_color.into();
|
||||
material.color = new_color.rgba_to_vec4();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ fn setup(mut commands: Commands, mut ui_materials: ResMut<Assets<CustomUiMateria
|
|||
..default()
|
||||
},
|
||||
material: ui_materials.add(CustomUiMaterial {
|
||||
color: Color::WHITE.into(),
|
||||
color: Color::WHITE.rgba_to_vec4(),
|
||||
}),
|
||||
..default()
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue