/ core / src / objects / color.rs
color.rs
  1  /// A struct that represents a color to use on objects, the clear color or labels.
  2  use glam::{Vec3, Vec4, vec3, vec4};
  3  use let_engine_macros::Vertex;
  4  
  5  /// Representation of a color in form of 4 `f32`'s for R, G, B and A.
  6  #[derive(Default, Clone, Copy, Debug, PartialEq, bytemuck::AnyBitPattern, Vertex)]
  7  #[repr(C)]
  8  pub struct Color {
  9      #[format(Rgba32Float)]
 10      rgba: [f32; 4],
 11  }
 12  
 13  /// Declaration
 14  impl Color {
 15      /// Full white color
 16      pub const WHITE: Self = Self::from_rgb(1.0, 1.0, 1.0);
 17  
 18      /// Black color with full alpha channel
 19      pub const BLACK: Self = Self::from_r(0.0);
 20  
 21      /// Full Black transparent color
 22      pub const TRANSPARENT: Self = Self::from_rgba(0.0, 0.0, 0.0, 0.0);
 23  
 24      /// Opaque red color
 25      pub const RED: Self = Self::from_r(1.0);
 26  
 27      /// Opaque green color
 28      pub const GREEN: Self = Self::from_g(1.0);
 29  
 30      /// Opaque blue color
 31      pub const BLUE: Self = Self::from_b(1.0);
 32  
 33      /// Makes a color from red, green, blue and alpha.
 34      #[inline]
 35      pub const fn from_rgba(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
 36          Self {
 37              rgba: [red, green, blue, alpha],
 38          }
 39      }
 40      /// Makes a color from red, green and blue.
 41      #[inline]
 42      pub const fn from_rgb(red: f32, green: f32, blue: f32) -> Self {
 43          Self {
 44              rgba: [red, green, blue, 1.0],
 45          }
 46      }
 47      /// Makes a color from red and green.
 48      #[inline]
 49      pub const fn from_rg(red: f32, green: f32) -> Self {
 50          Self {
 51              rgba: [red, green, 0.0, 1.0],
 52          }
 53      }
 54      /// Makes a color from red and blue.
 55      #[inline]
 56      pub const fn from_rb(red: f32, blue: f32) -> Self {
 57          Self {
 58              rgba: [red, 0.0, blue, 1.0],
 59          }
 60      }
 61      /// Makes a color from red.
 62      #[inline]
 63      pub const fn from_r(red: f32) -> Self {
 64          Self {
 65              rgba: [red, 0.0, 0.0, 1.0],
 66          }
 67      }
 68      /// Makes a color from green and blue.
 69      #[inline]
 70      pub const fn from_gb(green: f32, blue: f32) -> Self {
 71          Self {
 72              rgba: [0.0, green, blue, 1.0],
 73          }
 74      }
 75      /// Makes a color from green.
 76      #[inline]
 77      pub const fn from_g(green: f32) -> Self {
 78          Self {
 79              rgba: [0.0, green, 0.0, 1.0],
 80          }
 81      }
 82      /// Makes a color from blue.
 83      #[inline]
 84      pub const fn from_b(blue: f32) -> Self {
 85          Self {
 86              rgba: [0.0, 0.0, blue, 1.0],
 87          }
 88      }
 89  }
 90  
 91  /// Usage
 92  impl Color {
 93      /// Returns the red green blue and alpha of this color.
 94      #[inline]
 95      pub fn rgba(&self) -> [f32; 4] {
 96          self.rgba
 97      }
 98  
 99      /// Returns the red green and blue of this color.
100      #[inline]
101      pub fn rgb(&self) -> [f32; 3] {
102          [self.rgba[0], self.rgba[1], self.rgba[2]]
103      }
104  
105      /// Returns the red of this color.
106      #[inline]
107      pub fn r(&self) -> f32 {
108          self.rgba[0]
109      }
110  
111      /// Returns the green of this color.
112      #[inline]
113      pub fn g(&self) -> f32 {
114          self.rgba[1]
115      }
116  
117      /// Returns the blue of this color.
118      #[inline]
119      pub fn b(&self) -> f32 {
120          self.rgba[2]
121      }
122  
123      /// Returns the alpha or transparency of this color.
124      #[inline]
125      pub fn alpha(&self) -> f32 {
126          self.rgba[3]
127      }
128  
129      /// Sets the red channel of this color.
130      #[inline]
131      pub fn set_r(&mut self, red: f32) {
132          self.rgba[0] = red;
133      }
134  
135      /// Sets the green channel of this color.
136      #[inline]
137      pub fn set_g(&mut self, green: f32) {
138          self.rgba[1] = green;
139      }
140  
141      /// Sets the blue channel of this color.
142      #[inline]
143      pub fn set_b(&mut self, blue: f32) {
144          self.rgba[2] = blue;
145      }
146  
147      /// Sets the alpha channel of this color.
148      #[inline]
149      pub fn set_a(&mut self, alpha: f32) {
150          self.rgba[3] = alpha;
151      }
152  
153      /// Interpolates to the next color.
154      #[inline]
155      pub fn lerp(self, value: Self, s: f32) -> Self {
156          self * (1.0 - s) + value * s
157      }
158  }
159  
160  impl Color {
161      /// Returns `true` if this color is transparent, meaning the alpha value is not `1.0` or above.
162      #[inline]
163      pub fn is_transparent(&self) -> bool {
164          self.alpha() < 1.0
165      }
166  }
167  
168  impl From<[f32; 4]> for Color {
169      #[inline]
170      fn from(value: [f32; 4]) -> Self {
171          Color::from_rgba(value[0], value[1], value[2], value[3])
172      }
173  }
174  impl From<Vec4> for Color {
175      #[inline]
176      fn from(value: Vec4) -> Self {
177          Color::from_rgba(value.x, value.y, value.z, value.w)
178      }
179  }
180  impl From<[f32; 3]> for Color {
181      #[inline]
182      fn from(value: [f32; 3]) -> Self {
183          Color::from_rgb(value[0], value[1], value[2])
184      }
185  }
186  impl From<Vec3> for Color {
187      #[inline]
188      fn from(value: Vec3) -> Self {
189          Color::from_rgb(value.x, value.y, value.z)
190      }
191  }
192  impl From<f32> for Color {
193      #[inline]
194      fn from(value: f32) -> Self {
195          Color::from_r(value)
196      }
197  }
198  impl From<Color> for f32 {
199      #[inline]
200      fn from(value: Color) -> f32 {
201          value.r()
202      }
203  }
204  impl From<Color> for [f32; 3] {
205      #[inline]
206      fn from(value: Color) -> [f32; 3] {
207          value.rgb()
208      }
209  }
210  impl From<Color> for [f32; 4] {
211      #[inline]
212      fn from(value: Color) -> [f32; 4] {
213          value.rgba()
214      }
215  }
216  impl From<Color> for Vec3 {
217      #[inline]
218      fn from(value: Color) -> Vec3 {
219          vec3(value.r(), value.g(), value.b())
220      }
221  }
222  impl From<Color> for Vec4 {
223      #[inline]
224      fn from(value: Color) -> Vec4 {
225          vec4(value.r(), value.g(), value.b(), value.alpha())
226      }
227  }
228  impl std::ops::Add<Color> for Color {
229      type Output = Self;
230      #[inline]
231      fn add(self, rhs: Self) -> Self::Output {
232          Self {
233              rgba: [
234                  self.rgba[0] + rhs.rgba[0],
235                  self.rgba[1] + rhs.rgba[1],
236                  self.rgba[2] + rhs.rgba[2],
237                  self.rgba[3] + rhs.rgba[3],
238              ],
239          }
240      }
241  }
242  
243  impl std::ops::Sub<Color> for Color {
244      type Output = Self;
245      #[inline]
246      fn sub(self, rhs: Self) -> Self::Output {
247          Self {
248              rgba: [
249                  self.rgba[0] - rhs.rgba[0],
250                  self.rgba[1] - rhs.rgba[1],
251                  self.rgba[2] - rhs.rgba[2],
252                  self.rgba[3] - rhs.rgba[3],
253              ],
254          }
255      }
256  }
257  
258  impl std::ops::Mul<Color> for Color {
259      type Output = Self;
260      #[inline]
261      fn mul(self, rhs: Self) -> Self::Output {
262          Self {
263              rgba: [
264                  self.rgba[0] * rhs.rgba[0],
265                  self.rgba[1] * rhs.rgba[1],
266                  self.rgba[2] * rhs.rgba[2],
267                  self.rgba[3] * rhs.rgba[3],
268              ],
269          }
270      }
271  }
272  
273  impl std::ops::Div<Color> for Color {
274      type Output = Self;
275      #[inline]
276      fn div(self, rhs: Self) -> Self::Output {
277          Self {
278              rgba: [
279                  self.rgba[0] / rhs.rgba[0],
280                  self.rgba[1] / rhs.rgba[1],
281                  self.rgba[2] / rhs.rgba[2],
282                  self.rgba[3] / rhs.rgba[3],
283              ],
284          }
285      }
286  }
287  
288  impl std::ops::Add<f32> for Color {
289      type Output = Self;
290      #[inline]
291      fn add(self, rhs: f32) -> Self::Output {
292          Self {
293              rgba: self.rgba.map(|x| x + rhs),
294          }
295      }
296  }
297  
298  impl std::ops::Sub<f32> for Color {
299      type Output = Self;
300      #[inline]
301      fn sub(self, rhs: f32) -> Self::Output {
302          Self {
303              rgba: self.rgba.map(|x| x - rhs),
304          }
305      }
306  }
307  
308  impl std::ops::Mul<f32> for Color {
309      type Output = Self;
310      #[inline]
311      fn mul(self, rhs: f32) -> Self::Output {
312          Self {
313              rgba: self.rgba.map(|x| x * rhs),
314          }
315      }
316  }
317  
318  impl std::ops::Div<f32> for Color {
319      type Output = Self;
320      #[inline]
321      fn div(self, rhs: f32) -> Self::Output {
322          Self {
323              rgba: self.rgba.map(|x| x / rhs),
324          }
325      }
326  }
327  
328  impl std::ops::AddAssign<Color> for Color {
329      #[inline]
330      fn add_assign(&mut self, rhs: Self) {
331          self.rgba[0].add_assign(rhs.rgba[0]);
332          self.rgba[1].add_assign(rhs.rgba[1]);
333          self.rgba[2].add_assign(rhs.rgba[2]);
334          self.rgba[3].add_assign(rhs.rgba[3]);
335      }
336  }
337  
338  impl std::ops::SubAssign<Color> for Color {
339      #[inline]
340      fn sub_assign(&mut self, rhs: Self) {
341          self.rgba[0].sub_assign(rhs.rgba[0]);
342          self.rgba[1].sub_assign(rhs.rgba[1]);
343          self.rgba[2].sub_assign(rhs.rgba[2]);
344          self.rgba[3].sub_assign(rhs.rgba[3]);
345      }
346  }
347  
348  impl std::ops::MulAssign<Color> for Color {
349      #[inline]
350      fn mul_assign(&mut self, rhs: Self) {
351          self.rgba[0].mul_assign(rhs.rgba[0]);
352          self.rgba[1].mul_assign(rhs.rgba[1]);
353          self.rgba[2].mul_assign(rhs.rgba[2]);
354          self.rgba[3].mul_assign(rhs.rgba[3]);
355      }
356  }
357  
358  impl std::ops::DivAssign<Color> for Color {
359      #[inline]
360      fn div_assign(&mut self, rhs: Self) {
361          self.rgba[0].div_assign(rhs.rgba[0]);
362          self.rgba[1].div_assign(rhs.rgba[1]);
363          self.rgba[2].div_assign(rhs.rgba[2]);
364          self.rgba[3].div_assign(rhs.rgba[3]);
365      }
366  }
367  
368  impl std::ops::AddAssign<f32> for Color {
369      #[inline]
370      fn add_assign(&mut self, rhs: f32) {
371          for mut x in self.rgba {
372              x.add_assign(rhs)
373          }
374      }
375  }
376  
377  impl std::ops::SubAssign<f32> for Color {
378      #[inline]
379      fn sub_assign(&mut self, rhs: f32) {
380          for mut x in self.rgba {
381              x.sub_assign(rhs)
382          }
383      }
384  }
385  
386  impl std::ops::MulAssign<f32> for Color {
387      #[inline]
388      fn mul_assign(&mut self, rhs: f32) {
389          for mut x in self.rgba {
390              x.mul_assign(rhs)
391          }
392      }
393  }
394  
395  impl std::ops::DivAssign<f32> for Color {
396      #[inline]
397      fn div_assign(&mut self, rhs: f32) {
398          for mut x in self.rgba {
399              x.div_assign(rhs)
400          }
401      }
402  }
403  
404  impl std::ops::Deref for Color {
405      type Target = [f32; 4];
406  
407      fn deref(&self) -> &Self::Target {
408          &self.rgba
409      }
410  }
411  
412  impl std::ops::DerefMut for Color {
413      fn deref_mut(&mut self) -> &mut Self::Target {
414          &mut self.rgba
415      }
416  }