hyperion/models/
layouts.rs

1use super::{ClassicLedConfig, Led, Leds};
2
3/// Trait for converting a LED configuration to LEDs
4pub trait ToLeds {
5    fn to_leds(&self) -> Leds;
6}
7
8struct 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
32impl 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
60impl 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)) / self.ledstop as f32;
87        let stepv = (self.pttrv - self.pttlv) / 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) / 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 = (self.ptbrh - self.ptblh - (2. * self.edgehgap)) / self.ledsbottom as f32;
119        let stepv = (self.ptbrv - self.ptblv) / self.ledsbottom as f32;
120
121        leds.reserve(self.ledsbottom as _);
122        for i in 0..self.ledsbottom {
123            let i = i as f32;
124            let hmin = self.ovl_minus(self.ptblh + (steph * i) + self.edgehgap);
125            let hmax = self.ovl_plus(self.ptblh + (steph * (i + 1.)) + self.edgehgap);
126            let vmax = self.ptblv + (stepv * i);
127            let vmin = vmax - self.ledshdepth;
128
129            leds.push(Self::create_led(hmin, hmax, vmin, vmax));
130        }
131    }
132
133    fn create_left_leds(&self, leds: &mut Vec<Led>) {
134        let steph = (self.ptblh - self.pttlh) / self.ledsleft as f32;
135        let stepv = (self.ptblv - self.pttlv - (2. * self.edgevgap)) / self.ledsleft as f32;
136
137        leds.reserve(self.ledsleft as _);
138        for i in 0..self.ledsleft {
139            let i = i as f32;
140            let hmin = self.pttlh + (steph * i);
141            let hmax = hmin + self.ledsvdepth;
142            let vmin = self.ovl_minus(self.pttlv + (stepv * i) + self.edgevgap);
143            let vmax = self.ovl_plus(self.pttlv + (stepv * (i + 1.)) + self.edgevgap);
144
145            leds.push(Self::create_led(hmin, hmax, vmin, vmax));
146        }
147    }
148}
149
150impl ToLeds for ClassicLedParams {
151    fn to_leds(&self) -> Leds {
152        let mut leds = Vec::with_capacity(
153            (self.ledstop + self.ledsbottom + self.ledsleft + self.ledsright) as usize,
154        );
155
156        self.create_top_leds(&mut leds);
157        self.create_right_leds(&mut leds);
158        self.create_bottom_leds(&mut leds);
159        self.create_left_leds(&mut leds);
160
161        // Check LED gap pos
162        let ledsgpos = if self.ledsgpos + self.ledsglength > leds.len() as u32 {
163            (leds.len() as isize - self.ledsglength as isize).max(0) as usize
164        } else {
165            self.ledsglength as usize
166        };
167
168        // Check LED gap length
169        let ledsglength = if self.ledsglength >= leds.len() as u32 {
170            leds.len() as isize - self.ledsglength as isize - 1
171        } else {
172            self.ledsglength as _
173        };
174
175        if ledsglength > 0 {
176            leds.splice(
177                ledsgpos..(ledsgpos + ledsglength as usize),
178                std::iter::empty(),
179            );
180        }
181
182        if self.position < 0 {
183            leds.rotate_left(-self.position as _);
184        } else if self.position > 0 {
185            leds.rotate_right(self.position as _);
186        }
187
188        if self.reverse {
189            leds.reverse();
190        }
191
192        Leds { leds }
193    }
194}
195
196impl ToLeds for ClassicLedConfig {
197    fn to_leds(&self) -> Leds {
198        ClassicLedParams::from(self).to_leds()
199    }
200}