1use crate::traits::{Lerp, Real};
31use crate::vector::{TVec2, TVec3};
32
33pub struct LinearGradientBuilder<T: Real> {
36 start_pos: TVec2<T>,
37 start_col: TVec3<T>,
38
39 end_pos: TVec2<T>,
40 end_col: TVec3<T>,
41}
42
43impl<T: Real> LinearGradientBuilder<T> {
44 pub fn new() -> Self {
45 LinearGradientBuilder {
46 start_pos: TVec2::zero(),
47 start_col: TVec3::zero(),
48 end_pos: TVec2::zero(),
49 end_col: TVec3::zero(),
50 }
51 }
52
53 pub fn start(mut self, pos: TVec2<T>, color: TVec3<T>) -> Self {
54 self.start_pos = pos;
55 self.start_col = color;
56 self
57 }
58
59 pub fn end(mut self, pos: TVec2<T>, color: TVec3<T>) -> Self {
60 self.end_pos = pos;
61 self.end_col = color;
62 self
63 }
64
65 pub fn build(self) -> LinearGradient<T> {
66 let a = self.end_pos[0] - self.start_pos[0];
67 let b = self.end_pos[1] - self.start_pos[1];
68 LinearGradient {
69 start_col: self.start_col,
70 end_col: self.end_col,
71 a,
72 b,
73 c1: (a * self.start_pos[0]) + (b * self.start_pos[1]),
74 c2: (a * self.end_pos[0]) + (b * self.end_pos[1]),
75 }
76 }
77}
78
79impl<T: Real> Default for LinearGradientBuilder<T> {
80 fn default() -> Self {
81 Self::new()
82 }
83}
84
85#[derive(Clone)]
86pub struct LinearGradient<T: Real> {
87 start_col: TVec3<T>,
88 end_col: TVec3<T>,
89
90 a: T,
91 b: T,
92
93 c1: T,
94 c2: T,
95}
96
97impl<T: Real> LinearGradient<T> {
98 pub fn builder() -> LinearGradientBuilder<T> {
99 LinearGradientBuilder::new()
100 }
101
102 pub fn sample(&self, point: TVec2<T>) -> TVec3<T> {
103 let c = self.a * point[0] + self.b * point[1];
104 if c <= self.c1 {
105 self.start_col
106 } else if c >= self.c2 {
107 self.end_col
108 } else {
109 let factor =
110 (T::zero() * (self.c2 - c)) + (T::one() * (c - self.c1)) / (self.c2 - self.c1);
111 self.start_col.lerp(&self.end_col, factor)
112 }
113 }
114}