|
| 1 | +use super::{ClassicLedConfig, Led, Leds}; |
| 2 | + |
| 3 | +/// Trait for converting a LED configuration to LEDs |
| 4 | +pub trait ToLeds { |
| 5 | + fn to_leds(&self) -> Leds; |
| 6 | +} |
| 7 | + |
| 8 | +struct ClassicLedParams { |
| 9 | + ledstop: u32, |
| 10 | + ledsbottom: u32, |
| 11 | + ledsleft: u32, |
| 12 | + ledsright: u32, |
| 13 | + ledsglength: u32, |
| 14 | + ledsgpos: u32, |
| 15 | + position: i32, |
| 16 | + reverse: bool, |
| 17 | + ledsvdepth: f32, |
| 18 | + ledshdepth: f32, |
| 19 | + edgehgap: f32, |
| 20 | + edgevgap: f32, |
| 21 | + overlap: f32, |
| 22 | + ptblh: f32, |
| 23 | + ptblv: f32, |
| 24 | + ptbrh: f32, |
| 25 | + ptbrv: f32, |
| 26 | + pttlh: f32, |
| 27 | + pttlv: f32, |
| 28 | + pttrh: f32, |
| 29 | + pttrv: f32, |
| 30 | +} |
| 31 | + |
| 32 | +impl From<&ClassicLedConfig> for ClassicLedParams { |
| 33 | + fn from(c: &ClassicLedConfig) -> Self { |
| 34 | + Self { |
| 35 | + ledstop: c.top, |
| 36 | + ledsbottom: c.bottom, |
| 37 | + ledsleft: c.left, |
| 38 | + ledsright: c.right, |
| 39 | + ledsglength: c.glength, |
| 40 | + ledsgpos: c.gpos, |
| 41 | + position: c.position, |
| 42 | + reverse: c.reverse, |
| 43 | + ledsvdepth: c.vdepth as f32 / 100., |
| 44 | + ledshdepth: c.hdepth as f32 / 100., |
| 45 | + edgehgap: (c.edgegap as f32 / 200.) / (16. / 9.), |
| 46 | + edgevgap: c.edgegap as f32 / 200., |
| 47 | + overlap: c.overlap as f32 / 100., |
| 48 | + ptblh: c.pblh as f32 / 100., |
| 49 | + ptblv: c.pblv as f32 / 100., |
| 50 | + ptbrh: c.pbrh as f32 / 100., |
| 51 | + ptbrv: c.pbrv as f32 / 100., |
| 52 | + pttlh: c.ptlh as f32 / 100., |
| 53 | + pttlv: c.ptlv as f32 / 100., |
| 54 | + pttrh: c.ptrh as f32 / 100., |
| 55 | + pttrv: c.ptrv as f32 / 100., |
| 56 | + } |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +impl ClassicLedParams { |
| 61 | + fn round(x: f32) -> f32 { |
| 62 | + let factor = 1e4; |
| 63 | + (x * factor).round() / factor |
| 64 | + } |
| 65 | + |
| 66 | + fn create_led(hmin: f32, hmax: f32, vmin: f32, vmax: f32) -> Led { |
| 67 | + Led { |
| 68 | + hmin: Self::round(hmin), |
| 69 | + hmax: Self::round(hmax), |
| 70 | + vmin: Self::round(vmin), |
| 71 | + vmax: Self::round(vmax), |
| 72 | + color_order: None, |
| 73 | + name: None, |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + fn ovl_plus(&self, x: f32) -> f32 { |
| 78 | + (x + self.overlap).clamp(0., 1.) |
| 79 | + } |
| 80 | + |
| 81 | + fn ovl_minus(&self, x: f32) -> f32 { |
| 82 | + (x - self.overlap).clamp(0., 1.) |
| 83 | + } |
| 84 | + |
| 85 | + fn create_top_leds(&self, leds: &mut Vec<Led>) { |
| 86 | + let steph = (self.pttrh - self.pttlh - (2. * self.edgehgap)) as f32 / self.ledstop as f32; |
| 87 | + let stepv = (self.pttrv - self.pttlv) as f32 / self.ledstop as f32; |
| 88 | + |
| 89 | + leds.reserve(self.ledstop as _); |
| 90 | + for i in 0..self.ledstop { |
| 91 | + let i = i as f32; |
| 92 | + let hmin = self.ovl_minus(self.pttlh + (steph * i) + self.edgehgap); |
| 93 | + let hmax = self.ovl_plus(self.pttlh + (steph * (i + 1.)) + self.edgehgap); |
| 94 | + let vmin = self.pttlv + (stepv * i); |
| 95 | + let vmax = vmin + self.ledshdepth; |
| 96 | + |
| 97 | + leds.push(Self::create_led(hmin, hmax, vmin, vmax)); |
| 98 | + } |
| 99 | + } |
| 100 | + |
| 101 | + fn create_right_leds(&self, leds: &mut Vec<Led>) { |
| 102 | + let steph = (self.ptbrh - self.pttrh) as f32 / self.ledsright as f32; |
| 103 | + let stepv = (self.ptbrv - self.pttrv - (2. * self.edgevgap)) / self.ledsright as f32; |
| 104 | + |
| 105 | + leds.reserve(self.ledsright as _); |
| 106 | + for i in 0..self.ledsright { |
| 107 | + let i = i as f32; |
| 108 | + let hmax = self.pttrh + (steph * (i + 1.)); |
| 109 | + let hmin = hmax - self.ledsvdepth; |
| 110 | + let vmin = self.ovl_minus(self.pttrv + (stepv * i) + self.edgevgap); |
| 111 | + let vmax = self.ovl_plus(self.pttrv + (stepv * (i + 1.)) + self.edgevgap); |
| 112 | + |
| 113 | + leds.push(Self::create_led(hmin, hmax, vmin, vmax)); |
| 114 | + } |
| 115 | + } |
| 116 | + |
| 117 | + fn create_bottom_leds(&self, leds: &mut Vec<Led>) { |
| 118 | + let steph = |
| 119 | + (self.ptbrh - self.ptblh - (2. * self.edgehgap)) as f32 / self.ledsbottom as f32; |
| 120 | + let stepv = (self.ptbrv - self.ptblv) as f32 / self.ledsbottom as f32; |
| 121 | + |
| 122 | + leds.reserve(self.ledsbottom as _); |
| 123 | + for i in 0..self.ledsbottom { |
| 124 | + let i = i as f32; |
| 125 | + let hmin = self.ovl_minus(self.ptblh + (steph * i) + self.edgehgap); |
| 126 | + let hmax = self.ovl_plus(self.ptblh + (steph * (i + 1.)) + self.edgehgap); |
| 127 | + let vmax = self.ptblv + (stepv * i); |
| 128 | + let vmin = vmax - self.ledshdepth; |
| 129 | + |
| 130 | + leds.push(Self::create_led(hmin, hmax, vmin, vmax)); |
| 131 | + } |
| 132 | + } |
| 133 | + |
| 134 | + fn create_left_leds(&self, leds: &mut Vec<Led>) { |
| 135 | + let steph = (self.ptblh - self.pttlh) as f32 / self.ledsleft as f32; |
| 136 | + let stepv = (self.ptblv - self.pttlv - (2. * self.edgevgap)) as f32 / self.ledsleft as f32; |
| 137 | + |
| 138 | + leds.reserve(self.ledsleft as _); |
| 139 | + for i in 0..self.ledsleft { |
| 140 | + let i = i as f32; |
| 141 | + let hmin = self.pttlh + (steph * i); |
| 142 | + let hmax = hmin + self.ledsvdepth; |
| 143 | + let vmin = self.ovl_minus(self.pttlv + (stepv * i) + self.edgevgap); |
| 144 | + let vmax = self.ovl_plus(self.pttlv + (stepv * (i + 1.)) + self.edgevgap); |
| 145 | + |
| 146 | + leds.push(Self::create_led(hmin, hmax, vmin, vmax)); |
| 147 | + } |
| 148 | + } |
| 149 | +} |
| 150 | + |
| 151 | +impl ToLeds for ClassicLedParams { |
| 152 | + fn to_leds(&self) -> Leds { |
| 153 | + let mut leds = Vec::with_capacity( |
| 154 | + (self.ledstop + self.ledsbottom + self.ledsleft + self.ledsright) as usize, |
| 155 | + ); |
| 156 | + |
| 157 | + self.create_top_leds(&mut leds); |
| 158 | + self.create_right_leds(&mut leds); |
| 159 | + self.create_bottom_leds(&mut leds); |
| 160 | + self.create_left_leds(&mut leds); |
| 161 | + |
| 162 | + // Check LED gap pos |
| 163 | + let ledsgpos = if self.ledsgpos + self.ledsglength > leds.len() as _ { |
| 164 | + (leds.len() as isize - self.ledsglength as isize).max(0) as usize |
| 165 | + } else { |
| 166 | + self.ledsglength as usize |
| 167 | + }; |
| 168 | + |
| 169 | + // Check LED gap length |
| 170 | + let ledsglength = if self.ledsglength >= leds.len() as _ { |
| 171 | + leds.len() as isize - self.ledsglength as isize - 1 |
| 172 | + } else { |
| 173 | + self.ledsglength as _ |
| 174 | + }; |
| 175 | + |
| 176 | + if ledsglength > 0 { |
| 177 | + leds.splice( |
| 178 | + ledsgpos..(ledsgpos + ledsglength as usize), |
| 179 | + std::iter::empty(), |
| 180 | + ); |
| 181 | + } |
| 182 | + |
| 183 | + if self.position < 0 { |
| 184 | + leds.rotate_left(-self.position as _); |
| 185 | + } else if self.position > 0 { |
| 186 | + leds.rotate_right(self.position as _); |
| 187 | + } |
| 188 | + |
| 189 | + if self.reverse { |
| 190 | + leds.reverse(); |
| 191 | + } |
| 192 | + |
| 193 | + Leds { leds } |
| 194 | + } |
| 195 | +} |
| 196 | + |
| 197 | +impl ToLeds for ClassicLedConfig { |
| 198 | + fn to_leds(&self) -> Leds { |
| 199 | + ClassicLedParams::from(self).to_leds() |
| 200 | + } |
| 201 | +} |
0 commit comments