Skip to content

Commit 599e5e4

Browse files
alice-i-cecileAlice Cecileafonsolagerparrettbushrat011899
authored
Migrate from LegacyColor to bevy_color::Color (bevyengine#12163)
# Objective - As part of the migration process we need to a) see the end effect of the migration on user ergonomics b) check for serious perf regressions c) actually migrate the code - To accomplish this, I'm going to attempt to migrate all of the remaining user-facing usages of `LegacyColor` in one PR, being careful to keep a clean commit history. - Fixes bevyengine#12056. ## Solution I've chosen to use the polymorphic `Color` type as our standard user-facing API. - [x] Migrate `bevy_gizmos`. - [x] Take `impl Into<Color>` in all `bevy_gizmos` APIs - [x] Migrate sprites - [x] Migrate UI - [x] Migrate `ColorMaterial` - [x] Migrate `MaterialMesh2D` - [x] Migrate fog - [x] Migrate lights - [x] Migrate StandardMaterial - [x] Migrate wireframes - [x] Migrate clear color - [x] Migrate text - [x] Migrate gltf loader - [x] Register color types for reflection - [x] Remove `LegacyColor` - [x] Make sure CI passes Incidental improvements to ease migration: - added `Color::srgba_u8`, `Color::srgba_from_array` and friends - added `set_alpha`, `is_fully_transparent` and `is_fully_opaque` to the `Alpha` trait - add and immediately deprecate (lol) `Color::rgb` and friends in favor of more explicit and consistent `Color::srgb` - standardized on white and black for most example text colors - added vector field traits to `LinearRgba`: ~~`Add`, `Sub`, `AddAssign`, `SubAssign`,~~ `Mul<f32>` and `Div<f32>`. Multiplications and divisions do not scale alpha. `Add` and `Sub` have been cut from this PR. - added `LinearRgba` and `Srgba` `RED/GREEN/BLUE` - added `LinearRgba_to_f32_array` and `LinearRgba::to_u32` ## Migration Guide Bevy's color types have changed! Wherever you used a `bevy::render::Color`, a `bevy::color::Color` is used instead. These are quite similar! Both are enums storing a color in a specific color space (or to be more precise, using a specific color model). However, each of the different color models now has its own type. TODO... - `Color::rgba`, `Color::rgb`, `Color::rbga_u8`, `Color::rgb_u8`, `Color::rgb_from_array` are now `Color::srgba`, `Color::srgb`, `Color::srgba_u8`, `Color::srgb_u8` and `Color::srgb_from_array`. - `Color::set_a` and `Color::a` is now `Color::set_alpha` and `Color::alpha`. These are part of the `Alpha` trait in `bevy_color`. - `Color::is_fully_transparent` is now part of the `Alpha` trait in `bevy_color` - `Color::r`, `Color::set_r`, `Color::with_r` and the equivalents for `g`, `b` `h`, `s` and `l` have been removed due to causing silent relatively expensive conversions. Convert your `Color` into the desired color space, perform your operations there, and then convert it back into a polymorphic `Color` enum. - `Color::hex` is now `Srgba::hex`. Call `.into` or construct a `Color::Srgba` variant manually to convert it. - `WireframeMaterial`, `ExtractedUiNode`, `ExtractedDirectionalLight`, `ExtractedPointLight`, `ExtractedSpotLight` and `ExtractedSprite` now store a `LinearRgba`, rather than a polymorphic `Color` - `Color::rgb_linear` and `Color::rgba_linear` are now `Color::linear_rgb` and `Color::linear_rgba` - The various CSS color constants are no longer stored directly on `Color`. Instead, they're defined in the `Srgba` color space, and accessed via `bevy::color::palettes::css`. Call `.into()` on them to convert them into a `Color` for quick debugging use, and consider using the much prettier `tailwind` palette for prototyping. - The `LIME_GREEN` color has been renamed to `LIMEGREEN` to comply with the standard naming. - Vector field arithmetic operations on `Color` (add, subtract, multiply and divide by a f32) have been removed. Instead, convert your colors into `LinearRgba` space, and perform your operations explicitly there. This is particularly relevant when working with emissive or HDR colors, whose color channel values are routinely outside of the ordinary 0 to 1 range. - `Color::as_linear_rgba_f32` has been removed. Call `LinearRgba::to_f32_array` instead, converting if needed. - `Color::as_linear_rgba_u32` has been removed. Call `LinearRgba::to_u32` instead, converting if needed. - Several other color conversion methods to transform LCH or HSL colors into float arrays or `Vec` types have been removed. Please reimplement these externally or open a PR to re-add them if you found them particularly useful. - Various methods on `Color` such as `rgb` or `hsl` to convert the color into a specific color space have been removed. Convert into `LinearRgba`, then to the color space of your choice. - Various implicitly-converting color value methods on `Color` such as `r`, `g`, `b` or `h` have been removed. Please convert it into the color space of your choice, then check these properties. - `Color` no longer implements `AsBindGroup`. Store a `LinearRgba` internally instead to avoid conversion costs. --------- Co-authored-by: Alice Cecile <alice.i.cecil@gmail.com> Co-authored-by: Afonso Lage <lage.afonso@gmail.com> Co-authored-by: Rob Parrett <robparrett@gmail.com> Co-authored-by: Zachary Harrold <zac@harrold.com.au>
1 parent b24ab2e commit 599e5e4

File tree

180 files changed

+1372
-2808
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

180 files changed

+1372
-2808
lines changed

crates/bevy_color/src/color.rs

+99-4
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ impl Color {
4545
(*self).into()
4646
}
4747

48+
#[deprecated = "Use `Color::srgba` instead"]
49+
/// Creates a new [`Color`] object storing a [`Srgba`] color.
50+
pub const fn rgba(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
51+
Self::srgba(red, green, blue, alpha)
52+
}
53+
4854
/// Creates a new [`Color`] object storing a [`Srgba`] color.
4955
pub const fn srgba(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
5056
Self::Srgba(Srgba {
@@ -55,6 +61,12 @@ impl Color {
5561
})
5662
}
5763

64+
#[deprecated = "Use `Color::srgb` instead"]
65+
/// Creates a new [`Color`] object storing a [`Srgba`] color with an alpha of 1.0.
66+
pub const fn rgb(red: f32, green: f32, blue: f32) -> Self {
67+
Self::srgb(red, green, blue)
68+
}
69+
5870
/// Creates a new [`Color`] object storing a [`Srgba`] color with an alpha of 1.0.
5971
pub const fn srgb(red: f32, green: f32, blue: f32) -> Self {
6072
Self::Srgba(Srgba {
@@ -65,7 +77,69 @@ impl Color {
6577
})
6678
}
6779

68-
/// Createsa new [`Color`] object storing a [`LinearRgba`] color.
80+
#[deprecated = "Use `Color::srgb_from_array` instead"]
81+
/// Reads an array of floats to creates a new [`Color`] object storing a [`Srgba`] color with an alpha of 1.0.
82+
pub fn rgb_from_array([r, g, b]: [f32; 3]) -> Self {
83+
Self::Srgba(Srgba::rgb(r, g, b))
84+
}
85+
86+
/// Reads an array of floats to creates a new [`Color`] object storing a [`Srgba`] color with an alpha of 1.0.
87+
pub fn srgb_from_array(array: [f32; 3]) -> Self {
88+
Self::Srgba(Srgba {
89+
red: array[0],
90+
green: array[1],
91+
blue: array[2],
92+
alpha: 1.0,
93+
})
94+
}
95+
96+
#[deprecated = "Use `Color::srgba_u8` instead"]
97+
/// Creates a new [`Color`] object storing a [`Srgba`] color from [`u8`] values.
98+
///
99+
/// A value of 0 is interpreted as 0.0, and a value of 255 is interpreted as 1.0.
100+
pub fn rgba_u8(red: u8, green: u8, blue: u8, alpha: u8) -> Self {
101+
Self::srgba_u8(red, green, blue, alpha)
102+
}
103+
104+
/// Creates a new [`Color`] object storing a [`Srgba`] color from [`u8`] values.
105+
///
106+
/// A value of 0 is interpreted as 0.0, and a value of 255 is interpreted as 1.0.
107+
pub fn srgba_u8(red: u8, green: u8, blue: u8, alpha: u8) -> Self {
108+
Self::Srgba(Srgba {
109+
red: red as f32 / 255.0,
110+
green: green as f32 / 255.0,
111+
blue: blue as f32 / 255.0,
112+
alpha: alpha as f32 / 255.0,
113+
})
114+
}
115+
116+
#[deprecated = "Use `Color::srgb_u8` instead"]
117+
/// Creates a new [`Color`] object storing a [`Srgba`] color from [`u8`] values with an alpha of 1.0.
118+
///
119+
/// A value of 0 is interpreted as 0.0, and a value of 255 is interpreted as 1.0.
120+
pub fn rgb_u8(red: u8, green: u8, blue: u8) -> Self {
121+
Self::srgb_u8(red, green, blue)
122+
}
123+
124+
/// Creates a new [`Color`] object storing a [`Srgba`] color from [`u8`] values with an alpha of 1.0.
125+
///
126+
/// A value of 0 is interpreted as 0.0, and a value of 255 is interpreted as 1.0.
127+
pub fn srgb_u8(red: u8, green: u8, blue: u8) -> Self {
128+
Self::Srgba(Srgba {
129+
red: red as f32 / 255.0,
130+
green: green as f32 / 255.0,
131+
blue: blue as f32 / 255.0,
132+
alpha: 1.0,
133+
})
134+
}
135+
136+
#[deprecated = "Use Color::linear_rgba instead."]
137+
/// Creates a new [`Color`] object storing a [`LinearRgba`] color.
138+
pub const fn rbga_linear(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
139+
Self::linear_rgba(red, green, blue, alpha)
140+
}
141+
142+
/// Creates a new [`Color`] object storing a [`LinearRgba`] color.
69143
pub const fn linear_rgba(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
70144
Self::LinearRgba(LinearRgba {
71145
red,
@@ -75,7 +149,13 @@ impl Color {
75149
})
76150
}
77151

78-
/// a new [`Color`] object storing a [`LinearRgba`] color with an alpha of 1.0.
152+
#[deprecated = "Use Color::linear_rgb instead."]
153+
/// Creates a new [`Color`] object storing a [`LinearRgba`] color with an alpha of 1.0.
154+
pub const fn rgb_linear(red: f32, green: f32, blue: f32) -> Self {
155+
Self::linear_rgb(red, green, blue)
156+
}
157+
158+
/// Creates a new [`Color`] object storing a [`LinearRgba`] color with an alpha of 1.0.
79159
pub const fn linear_rgb(red: f32, green: f32, blue: f32) -> Self {
80160
Self::LinearRgba(LinearRgba {
81161
red,
@@ -241,8 +321,8 @@ impl Color {
241321
/// A fully black [`Color::LinearRgba`] color with an alpha of 1.0.
242322
pub const BLACK: Self = Self::linear_rgb(0., 0., 0.);
243323

244-
/// A fully transparent [`Color::LinearRgba`] color.
245-
pub const TRANSPARENT: Self = Self::linear_rgba(0., 0., 0., 0.);
324+
/// A fully transparent [`Color::LinearRgba`] color with 0 red, green and blue.
325+
pub const NONE: Self = Self::linear_rgba(0., 0., 0., 0.);
246326
}
247327

248328
impl Default for Color {
@@ -286,6 +366,21 @@ impl Alpha for Color {
286366
Color::Xyza(x) => x.alpha(),
287367
}
288368
}
369+
370+
fn set_alpha(&mut self, alpha: f32) {
371+
match self {
372+
Color::Srgba(x) => x.set_alpha(alpha),
373+
Color::LinearRgba(x) => x.set_alpha(alpha),
374+
Color::Hsla(x) => x.set_alpha(alpha),
375+
Color::Hsva(x) => x.set_alpha(alpha),
376+
Color::Hwba(x) => x.set_alpha(alpha),
377+
Color::Laba(x) => x.set_alpha(alpha),
378+
Color::Lcha(x) => x.set_alpha(alpha),
379+
Color::Oklaba(x) => x.set_alpha(alpha),
380+
Color::Oklcha(x) => x.set_alpha(alpha),
381+
Color::Xyza(x) => x.set_alpha(alpha),
382+
}
383+
}
289384
}
290385

291386
impl From<Srgba> for Color {

crates/bevy_color/src/color_ops.rs

+13
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,17 @@ pub trait Alpha: Sized {
4747

4848
/// Return a the alpha component of this color.
4949
fn alpha(&self) -> f32;
50+
51+
/// Sets the alpha component of this color.
52+
fn set_alpha(&mut self, alpha: f32);
53+
54+
/// Is the alpha component of this color less than or equal to 0.0?
55+
fn is_fully_transparent(&self) -> bool {
56+
self.alpha() <= 0.0
57+
}
58+
59+
/// Is the alpha component of this color greater than or equal to 1.0?
60+
fn is_fully_opaque(&self) -> bool {
61+
self.alpha() >= 1.0
62+
}
5063
}

crates/bevy_color/src/hsla.rs

+5
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ impl Alpha for Hsla {
134134
fn alpha(&self) -> f32 {
135135
self.alpha
136136
}
137+
138+
#[inline]
139+
fn set_alpha(&mut self, alpha: f32) {
140+
self.alpha = alpha;
141+
}
137142
}
138143

139144
impl Luminance for Hsla {

crates/bevy_color/src/hsva.rs

+5
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ impl Alpha for Hsva {
8484
fn alpha(&self) -> f32 {
8585
self.alpha
8686
}
87+
88+
#[inline]
89+
fn set_alpha(&mut self, alpha: f32) {
90+
self.alpha = alpha;
91+
}
8792
}
8893

8994
impl From<Hsva> for Hwba {

crates/bevy_color/src/hwba.rs

+5
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ impl Alpha for Hwba {
8888
fn alpha(&self) -> f32 {
8989
self.alpha
9090
}
91+
92+
#[inline]
93+
fn set_alpha(&mut self, alpha: f32) {
94+
self.alpha = alpha;
95+
}
9196
}
9297

9398
impl From<Srgba> for Hwba {

crates/bevy_color/src/laba.rs

+5
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ impl Alpha for Laba {
103103
fn alpha(&self) -> f32 {
104104
self.alpha
105105
}
106+
107+
#[inline]
108+
fn set_alpha(&mut self, alpha: f32) {
109+
self.alpha = alpha;
110+
}
106111
}
107112

108113
impl Luminance for Laba {

crates/bevy_color/src/lcha.rs

+5
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ impl Alpha for Lcha {
130130
fn alpha(&self) -> f32 {
131131
self.alpha
132132
}
133+
134+
#[inline]
135+
fn set_alpha(&mut self, alpha: f32) {
136+
self.alpha = alpha;
137+
}
133138
}
134139

135140
impl Luminance for Lcha {

crates/bevy_color/src/linear_rgba.rs

+93
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::ops::{Div, Mul};
2+
13
use crate::{color_difference::EuclideanDistance, Alpha, Luminance, Mix, StandardColor};
24
use bevy_math::Vec4;
35
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
@@ -50,6 +52,30 @@ impl LinearRgba {
5052
alpha: 0.0,
5153
};
5254

55+
/// A fully red color with full alpha.
56+
pub const RED: Self = Self {
57+
red: 1.0,
58+
green: 0.0,
59+
blue: 0.0,
60+
alpha: 1.0,
61+
};
62+
63+
/// A fully green color with full alpha.
64+
pub const GREEN: Self = Self {
65+
red: 0.0,
66+
green: 1.0,
67+
blue: 0.0,
68+
alpha: 1.0,
69+
};
70+
71+
/// A fully blue color with full alpha.
72+
pub const BLUE: Self = Self {
73+
red: 0.0,
74+
green: 0.0,
75+
blue: 1.0,
76+
alpha: 1.0,
77+
};
78+
5379
/// An invalid color.
5480
///
5581
/// This type can be used to represent an invalid color value;
@@ -127,6 +153,26 @@ impl LinearRgba {
127153
self.mix_assign(Self::new(1.0, 1.0, 1.0, self.alpha), adjustment);
128154
}
129155
}
156+
157+
/// Converts the color into a [f32; 4] array in RGBA order.
158+
///
159+
/// This is useful for passing the color to a shader.
160+
pub fn to_f32_array(&self) -> [f32; 4] {
161+
[self.red, self.green, self.blue, self.alpha]
162+
}
163+
164+
/// Converts this color to a u32.
165+
///
166+
/// Maps the RGBA channels in RGBA order to a little-endian byte array (GPUs are little-endian).
167+
/// `A` will be the most significant byte and `R` the least significant.
168+
pub fn as_u32(&self) -> u32 {
169+
u32::from_le_bytes([
170+
(self.red * 255.0) as u8,
171+
(self.green * 255.0) as u8,
172+
(self.blue * 255.0) as u8,
173+
(self.alpha * 255.0) as u8,
174+
])
175+
}
130176
}
131177

132178
impl Default for LinearRgba {
@@ -193,6 +239,11 @@ impl Alpha for LinearRgba {
193239
fn alpha(&self) -> f32 {
194240
self.alpha
195241
}
242+
243+
#[inline]
244+
fn set_alpha(&mut self, alpha: f32) {
245+
self.alpha = alpha;
246+
}
196247
}
197248

198249
impl EuclideanDistance for LinearRgba {
@@ -228,6 +279,48 @@ impl From<LinearRgba> for wgpu::Color {
228279
}
229280
}
230281

282+
/// All color channels are scaled directly,
283+
/// but alpha is unchanged.
284+
///
285+
/// Values are not clamped.
286+
impl Mul<f32> for LinearRgba {
287+
type Output = Self;
288+
289+
fn mul(self, rhs: f32) -> Self {
290+
Self {
291+
red: self.red * rhs,
292+
green: self.green * rhs,
293+
blue: self.blue * rhs,
294+
alpha: self.alpha,
295+
}
296+
}
297+
}
298+
299+
impl Mul<LinearRgba> for f32 {
300+
type Output = LinearRgba;
301+
302+
fn mul(self, rhs: LinearRgba) -> LinearRgba {
303+
rhs * self
304+
}
305+
}
306+
307+
/// All color channels are scaled directly,
308+
/// but alpha is unchanged.
309+
///
310+
/// Values are not clamped.
311+
impl Div<f32> for LinearRgba {
312+
type Output = Self;
313+
314+
fn div(self, rhs: f32) -> Self {
315+
Self {
316+
red: self.red / rhs,
317+
green: self.green / rhs,
318+
blue: self.blue / rhs,
319+
alpha: self.alpha,
320+
}
321+
}
322+
}
323+
231324
// [`LinearRgba`] is intended to be used with shaders
232325
// So it's the only color type that implements [`ShaderType`] to make it easier to use inside shaders
233326
impl encase::ShaderType for LinearRgba {

crates/bevy_color/src/oklaba.rs

+5
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ impl Alpha for Oklaba {
9999
fn alpha(&self) -> f32 {
100100
self.alpha
101101
}
102+
103+
#[inline]
104+
fn set_alpha(&mut self, alpha: f32) {
105+
self.alpha = alpha;
106+
}
102107
}
103108

104109
impl Luminance for Oklaba {

crates/bevy_color/src/oklcha.rs

+5
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ impl Alpha for Oklcha {
129129
fn alpha(&self) -> f32 {
130130
self.alpha
131131
}
132+
133+
#[inline]
134+
fn set_alpha(&mut self, alpha: f32) {
135+
self.alpha = alpha;
136+
}
132137
}
133138

134139
impl Luminance for Oklcha {

0 commit comments

Comments
 (0)