@@ -11,6 +11,8 @@ use bevy_property::Property;
11
11
use serde:: { Deserialize , Serialize } ;
12
12
use std:: ops:: { Add , AddAssign , Mul , MulAssign } ;
13
13
14
+ // TODO: Separate types for non-linear sRGB and linear sRGB, with conversions between
15
+ // see comment on bevy issue #688 https://github.com/bevyengine/bevy/pull/688#issuecomment-711414011
14
16
/// RGBA color in the Linear sRGB colorspace (often colloquially referred to as "linear", "RGB", or "linear RGB").
15
17
#[ repr( C ) ]
16
18
#[ derive( Debug , Clone , Copy , PartialEq , Serialize , Deserialize , Property ) ]
@@ -76,6 +78,7 @@ impl Color {
76
78
}
77
79
}
78
80
81
+ /// New ``Color`` from sRGB colorspace.
79
82
pub fn hex < T : AsRef < str > > ( hex : T ) -> Result < Color , HexColorError > {
80
83
let hex = hex. as_ref ( ) ;
81
84
@@ -134,72 +137,90 @@ impl Color {
134
137
red : self . red . nonlinear_to_linear_srgb ( ) ,
135
138
green : self . green . nonlinear_to_linear_srgb ( ) ,
136
139
blue : self . blue . nonlinear_to_linear_srgb ( ) ,
137
- alpha : self . alpha , //alpha is always linear
140
+ alpha : self . alpha , // alpha is always linear
138
141
}
139
142
}
140
143
141
144
// non-linear-sRGB Component Getter
145
+
146
+ /// Get red in sRGB colorspace.
142
147
pub fn r ( & self ) -> f32 {
143
148
self . red . linear_to_nonlinear_srgb ( )
144
149
}
145
150
151
+ /// Get green in sRGB colorspace.
146
152
pub fn g ( & self ) -> f32 {
147
153
self . green . linear_to_nonlinear_srgb ( )
148
154
}
149
155
156
+ /// Get blue in sRGB colorspace.
150
157
pub fn b ( & self ) -> f32 {
151
158
self . blue . linear_to_nonlinear_srgb ( )
152
159
}
153
160
154
161
// linear-sRGB Component Getter
155
- pub fn g_linear ( & self ) -> f32 {
156
- self . green
157
- }
158
162
163
+ /// Get red in linear colorspace.
159
164
pub fn r_linear ( & self ) -> f32 {
160
165
self . red
161
166
}
162
167
168
+ /// Get green in linear colorspace.
169
+ pub fn g_linear ( & self ) -> f32 {
170
+ self . green
171
+ }
172
+
173
+ /// Get blue in linear colorspace.
163
174
pub fn b_linear ( & self ) -> f32 {
164
175
self . blue
165
176
}
166
177
178
+ /// Get alpha.
167
179
pub fn a ( & self ) -> f32 {
168
180
self . alpha
169
181
}
170
182
171
183
// non-linear-sRGB Component Setter
184
+
185
+ /// Set red in sRGB colorspace.
172
186
pub fn set_r ( & mut self , r : f32 ) -> & mut Self {
173
187
self . red = r. nonlinear_to_linear_srgb ( ) ;
174
188
self
175
189
}
176
190
191
+ /// Set green in sRGB colorspace.
177
192
pub fn set_g ( & mut self , g : f32 ) -> & mut Self {
178
193
self . green = g. nonlinear_to_linear_srgb ( ) ;
179
194
self
180
195
}
181
196
197
+ /// Set blue in sRGB colorspace.
182
198
pub fn set_b ( & mut self , b : f32 ) -> & mut Self {
183
199
self . blue = b. nonlinear_to_linear_srgb ( ) ;
184
200
self
185
201
}
186
202
187
203
// linear-sRGB Component Setter
204
+
205
+ /// Set red in linear colorspace.
188
206
pub fn set_r_linear ( & mut self , r : f32 ) -> & mut Self {
189
207
self . red = r;
190
208
self
191
209
}
192
210
211
+ /// Set green in linear colorspace.
193
212
pub fn set_g_linear ( & mut self , g : f32 ) -> & mut Self {
194
213
self . green = g;
195
214
self
196
215
}
197
216
217
+ /// Set blue in linear colorspace.
198
218
pub fn set_b_linear ( & mut self , b : f32 ) -> & mut Self {
199
219
self . blue = b;
200
220
self
201
221
}
202
222
223
+ /// Set alpha.
203
224
pub fn set_a ( & mut self , a : f32 ) -> & mut Self {
204
225
self . alpha = a;
205
226
self
@@ -249,91 +270,119 @@ impl Add<Vec4> for Color {
249
270
}
250
271
}
251
272
252
- impl From < Vec4 > for Color {
253
- fn from ( vec4 : Vec4 ) -> Self {
254
- Color {
255
- red : vec4. x ( ) ,
256
- green : vec4. y ( ) ,
257
- blue : vec4. z ( ) ,
258
- alpha : vec4. w ( ) ,
259
- }
273
+ impl From < Color > for [ f32 ; 4 ] {
274
+ fn from ( color : Color ) -> Self {
275
+ [ color. r ( ) , color. g ( ) , color. b ( ) , color. a ( ) ]
260
276
}
261
277
}
262
278
263
279
impl From < [ f32 ; 4 ] > for Color {
264
- fn from ( value : [ f32 ; 4 ] ) -> Self {
265
- Color :: rgba ( value[ 0 ] , value[ 1 ] , value[ 2 ] , value[ 3 ] )
280
+ fn from ( [ r, g, b, a] : [ f32 ; 4 ] ) -> Self {
281
+ Color :: rgba ( r, g, b, a)
282
+ }
283
+ }
284
+
285
+ impl From < Color > for Vec4 {
286
+ fn from ( color : Color ) -> Self {
287
+ Vec4 :: new ( color. r ( ) , color. g ( ) , color. b ( ) , color. a ( ) )
266
288
}
267
289
}
268
290
269
- impl Into < [ f32 ; 4 ] > for Color {
270
- fn into ( self ) -> [ f32 ; 4 ] {
271
- [ self . red , self . green , self . blue , self . alpha ]
291
+ impl From < Vec4 > for Color {
292
+ fn from ( vec4 : Vec4 ) -> Self {
293
+ Color :: rgba ( vec4 . x ( ) , vec4 . y ( ) , vec4 . z ( ) , vec4 . w ( ) )
272
294
}
273
295
}
274
296
275
297
impl Mul < f32 > for Color {
276
298
type Output = Color ;
277
299
278
300
fn mul ( self , rhs : f32 ) -> Self :: Output {
279
- Color {
280
- red : self . red * rhs,
281
- green : self . green * rhs,
282
- blue : self . blue * rhs,
283
- alpha : self . alpha * rhs,
284
- }
301
+ Color :: rgba ( self . r ( ) * rhs, self . g ( ) * rhs, self . b ( ) * rhs, self . a ( ) )
285
302
}
286
303
}
287
304
288
305
impl MulAssign < f32 > for Color {
289
306
fn mul_assign ( & mut self , rhs : f32 ) {
290
- self . red *= rhs;
291
- self . green *= rhs;
292
- self . blue *= rhs;
293
- self . alpha *= rhs;
307
+ self . set_r ( self . r ( ) * rhs) ;
308
+ self . set_g ( self . g ( ) * rhs) ;
309
+ self . set_b ( self . b ( ) * rhs) ;
294
310
}
295
311
}
296
312
297
313
impl Mul < Vec4 > for Color {
298
314
type Output = Color ;
299
315
300
316
fn mul ( self , rhs : Vec4 ) -> Self :: Output {
301
- Color {
302
- red : self . red * rhs. x ( ) ,
303
- green : self . green * rhs. y ( ) ,
304
- blue : self . blue * rhs. z ( ) ,
305
- alpha : self . alpha * rhs. w ( ) ,
306
- }
317
+ Color :: rgba (
318
+ self . r ( ) * rhs. x ( ) ,
319
+ self . g ( ) * rhs. y ( ) ,
320
+ self . b ( ) * rhs. z ( ) ,
321
+ self . a ( ) * rhs. w ( ) ,
322
+ )
307
323
}
308
324
}
309
325
310
326
impl MulAssign < Vec4 > for Color {
311
327
fn mul_assign ( & mut self , rhs : Vec4 ) {
312
- self . red *= rhs. x ( ) ;
313
- self . green *= rhs. y ( ) ;
314
- self . blue *= rhs. z ( ) ;
315
- self . alpha *= rhs. w ( ) ;
328
+ self . set_r ( self . r ( ) * rhs. x ( ) ) ;
329
+ self . set_g ( self . g ( ) * rhs. y ( ) ) ;
330
+ self . set_b ( self . b ( ) * rhs. z ( ) ) ;
331
+ self . set_a ( self . a ( ) * rhs. w ( ) ) ;
316
332
}
317
333
}
318
334
319
335
impl Mul < Vec3 > for Color {
320
336
type Output = Color ;
321
337
322
338
fn mul ( self , rhs : Vec3 ) -> Self :: Output {
323
- Color {
324
- red : self . red * rhs. x ( ) ,
325
- green : self . green * rhs. y ( ) ,
326
- blue : self . blue * rhs. z ( ) ,
327
- alpha : self . alpha ,
328
- }
339
+ Color :: rgba (
340
+ self . r ( ) * rhs. x ( ) ,
341
+ self . g ( ) * rhs. y ( ) ,
342
+ self . b ( ) * rhs. z ( ) ,
343
+ self . a ( ) ,
344
+ )
329
345
}
330
346
}
331
347
332
348
impl MulAssign < Vec3 > for Color {
333
349
fn mul_assign ( & mut self , rhs : Vec3 ) {
334
- self . red *= rhs. x ( ) ;
335
- self . green *= rhs. y ( ) ;
336
- self . blue *= rhs. z ( ) ;
350
+ self . set_r ( self . r ( ) * rhs. x ( ) ) ;
351
+ self . set_g ( self . g ( ) * rhs. y ( ) ) ;
352
+ self . set_b ( self . b ( ) * rhs. z ( ) ) ;
353
+ }
354
+ }
355
+
356
+ impl Mul < [ f32 ; 4 ] > for Color {
357
+ type Output = Color ;
358
+
359
+ fn mul ( self , [ r, g, b, a] : [ f32 ; 4 ] ) -> Self :: Output {
360
+ Color :: rgba ( self . r ( ) * r, self . g ( ) * g, self . b ( ) * b, self . a ( ) * a)
361
+ }
362
+ }
363
+
364
+ impl MulAssign < [ f32 ; 4 ] > for Color {
365
+ fn mul_assign ( & mut self , [ r, g, b, a] : [ f32 ; 4 ] ) {
366
+ self . set_r ( self . r ( ) * r) ;
367
+ self . set_g ( self . g ( ) * g) ;
368
+ self . set_b ( self . b ( ) * b) ;
369
+ self . set_a ( self . a ( ) * a) ;
370
+ }
371
+ }
372
+
373
+ impl Mul < [ f32 ; 3 ] > for Color {
374
+ type Output = Color ;
375
+
376
+ fn mul ( self , [ r, g, b] : [ f32 ; 3 ] ) -> Self :: Output {
377
+ Color :: rgba ( self . r ( ) * r, self . g ( ) * g, self . b ( ) * b, self . a ( ) )
378
+ }
379
+ }
380
+
381
+ impl MulAssign < [ f32 ; 3 ] > for Color {
382
+ fn mul_assign ( & mut self , [ r, g, b] : [ f32 ; 3 ] ) {
383
+ self . set_r ( self . r ( ) * r) ;
384
+ self . set_g ( self . g ( ) * g) ;
385
+ self . set_b ( self . b ( ) * b) ;
337
386
}
338
387
}
339
388
@@ -359,6 +408,12 @@ pub enum ColorSource {
359
408
Texture ( Handle < Texture > ) ,
360
409
}
361
410
411
+ impl From < [ f32 ; 4 ] > for ColorSource {
412
+ fn from ( f32s : [ f32 ; 4 ] ) -> Self {
413
+ ColorSource :: Color ( f32s. into ( ) )
414
+ }
415
+ }
416
+
362
417
impl From < Vec4 > for ColorSource {
363
418
fn from ( vec4 : Vec4 ) -> Self {
364
419
ColorSource :: Color ( vec4. into ( ) )
@@ -449,3 +504,98 @@ fn test_hex_color() {
449
504
450
505
assert ! ( Color :: hex( "1234567890" ) . is_err( ) ) ;
451
506
}
507
+
508
+ #[ test]
509
+ fn test_conversions_vec4 ( ) {
510
+ let starting_vec4 = Vec4 :: new ( 0.4 , 0.5 , 0.6 , 1.0 ) ;
511
+ let starting_color = Color :: from ( starting_vec4) ;
512
+
513
+ assert_eq ! ( starting_vec4, Vec4 :: from( starting_color) , ) ;
514
+
515
+ let transformation = Vec4 :: new ( 0.5 , 0.5 , 0.5 , 1.0 ) ;
516
+
517
+ assert_eq ! (
518
+ starting_color * transformation,
519
+ Color :: from( starting_vec4 * transformation) ,
520
+ ) ;
521
+ }
522
+
523
+ #[ test]
524
+ fn test_mul_and_mulassign_f32 ( ) {
525
+ let transformation = 0.5 ;
526
+ let starting_color = Color :: rgba ( 0.4 , 0.5 , 0.6 , 1.0 ) ;
527
+
528
+ assert_eq ! (
529
+ starting_color * transformation,
530
+ Color :: rgba( 0.4 * 0.5 , 0.5 * 0.5 , 0.6 * 0.5 , 1.0 ) ,
531
+ ) ;
532
+
533
+ let mut mutated_color = starting_color;
534
+ mutated_color *= transformation;
535
+
536
+ assert_eq ! ( starting_color * transformation, mutated_color, ) ;
537
+ }
538
+
539
+ #[ test]
540
+ fn test_mul_and_mulassign_f32by3 ( ) {
541
+ let transformation = [ 0.4 , 0.5 , 0.6 ] ;
542
+ let starting_color = Color :: rgba ( 0.4 , 0.5 , 0.6 , 1.0 ) ;
543
+
544
+ assert_eq ! (
545
+ starting_color * transformation,
546
+ Color :: rgba( 0.4 * 0.4 , 0.5 * 0.5 , 0.6 * 0.6 , 1.0 ) ,
547
+ ) ;
548
+
549
+ let mut mutated_color = starting_color;
550
+ mutated_color *= transformation;
551
+
552
+ assert_eq ! ( starting_color * transformation, mutated_color, ) ;
553
+ }
554
+
555
+ #[ test]
556
+ fn test_mul_and_mulassign_f32by4 ( ) {
557
+ let transformation = [ 0.4 , 0.5 , 0.6 , 0.9 ] ;
558
+ let starting_color = Color :: rgba ( 0.4 , 0.5 , 0.6 , 1.0 ) ;
559
+
560
+ assert_eq ! (
561
+ starting_color * transformation,
562
+ Color :: rgba( 0.4 * 0.4 , 0.5 * 0.5 , 0.6 * 0.6 , 1.0 * 0.9 ) ,
563
+ ) ;
564
+
565
+ let mut mutated_color = starting_color;
566
+ mutated_color *= transformation;
567
+
568
+ assert_eq ! ( starting_color * transformation, mutated_color, ) ;
569
+ }
570
+
571
+ #[ test]
572
+ fn test_mul_and_mulassign_vec3 ( ) {
573
+ let transformation = Vec3 :: new ( 0.2 , 0.3 , 0.4 ) ;
574
+ let starting_color = Color :: rgba ( 0.4 , 0.5 , 0.6 , 1.0 ) ;
575
+
576
+ assert_eq ! (
577
+ starting_color * transformation,
578
+ Color :: rgba( 0.4 * 0.2 , 0.5 * 0.3 , 0.6 * 0.4 , 1.0 ) ,
579
+ ) ;
580
+
581
+ let mut mutated_color = starting_color;
582
+ mutated_color *= transformation;
583
+
584
+ assert_eq ! ( starting_color * transformation, mutated_color, ) ;
585
+ }
586
+
587
+ #[ test]
588
+ fn test_mul_and_mulassign_vec4 ( ) {
589
+ let transformation = Vec4 :: new ( 0.2 , 0.3 , 0.4 , 0.5 ) ;
590
+ let starting_color = Color :: rgba ( 0.4 , 0.5 , 0.6 , 1.0 ) ;
591
+
592
+ assert_eq ! (
593
+ starting_color * transformation,
594
+ Color :: rgba( 0.4 * 0.2 , 0.5 * 0.3 , 0.6 * 0.4 , 1.0 * 0.5 ) ,
595
+ ) ;
596
+
597
+ let mut mutated_color = starting_color;
598
+ mutated_color *= transformation;
599
+
600
+ assert_eq ! ( starting_color * transformation, mutated_color, ) ;
601
+ }
0 commit comments