Lamp-Da 0.1
A compact lantern project
Loading...
Searching...
No Matches
overlay.hpp
Go to the documentation of this file.
1
5#ifndef MODES_DRAW_OVERLAY_HPP
6#define MODES_DRAW_OVERLAY_HPP
7
8namespace lampda::modes::draw {
10namespace overlay {
11
13enum class ElementType : uint8_t
14{
15 NONE = 0,
16 RAMP,
17 DOT,
18};
19
20namespace __private {
21
23struct Color
24{
25 uint8_t red;
26 uint8_t green;
27 uint8_t blue;
28 uint32_t get_color() const { return (red << 16) | (green << 8) | blue; }
29};
30
35{
36 ElementType type = ElementType::NONE;
37 uint8_t progress;
38
39 uint16_t coordinateX;
40 uint16_t coordinateY;
41
43
44 int32_t timeout_ms = -1;
45};
46
47} // namespace __private
48
49template<int UIElementSize = 16, uint8_t freezeSize = 5, uint8_t nbBlackLines = 2> class Manager
50{
51public:
52 Manager() : activeUiElements(0) {}
53
57 void display_update(auto& ctx)
58 {
59 assert(activeUiElements < UIElementSize);
60
61 // restore first led skip to be able to draw
62 ctx.skipFirstLedsForFrames(0);
63
64 if (activeUiElements == 0)
65 return;
66
67 // clear overlay area first
68 for (uint8_t i = 0; i < ctx.lamp.maxWidth * nbBlackLines; ++i)
69 {
70 ctx.lamp.setPixelColor(i, 0);
71 }
72
73 // keep track of the last active element index
74 size_t lastActiveElementIndex = 0;
75 const auto timeNow = ctx.lamp.now;
76 const size_t activeUiElementsToDisplay = activeUiElements;
77 // display all elements
78 for (uint8_t i = 0; i < activeUiElementsToDisplay; ++i)
79 {
80 const auto elementTimeout = elements[i].timeout_ms;
81 // auto deletion of element
82 if (elementTimeout > 0 and timeNow > elementTimeout)
83 {
84 // remove one active element
85 if (activeUiElements > 0)
86 --activeUiElements;
87 }
88 else
89 {
90 drawElement(elements[i], ctx);
91
92 // if an element before this was delete, shift this element index
93 if (i != lastActiveElementIndex)
94 {
95 // shift the saved elements
96 elements[lastActiveElementIndex] = elements[i];
97 }
98 ++lastActiveElementIndex;
99 }
100 }
101
102 // relock the display capabilities for the remaining time
103 ctx.skipFirstLedsForFrames(ctx.lamp.maxWidth * nbBlackLines, freezeSize);
104 }
105
107 void clear() { activeUiElements = 0; }
108
110 uint8_t get_element_count(const ElementType type) const
111 {
112 uint8_t cnt = 0;
113 for (uint8_t i = 0; i < activeUiElements; ++i)
114 {
115 // find elements of a type
116 if (elements[i].type == type)
117 {
118 cnt++;
119 }
120 }
121 return cnt;
122 }
123
134 bool add_ui_element(const auto& ctx,
135 const ElementType type,
136 const colors::PaletteTy& palette,
137 const uint16_t coordinateX = 0,
138 const uint16_t coordinateY = 0,
139 const uint8_t progress = 0,
140 const uint32_t activityDelay_ms = 50)
141 {
142 if (activeUiElements >= UIElementSize - 1)
143 return false;
144
145 // set the UI element
146 __private::UIElement& element = elements[activeUiElements];
147 element.type = type;
148 element.progress = progress;
149 element.coordinateX = coordinateX;
150 element.coordinateY = coordinateY;
151 element.color = palette;
152 // set optionnal auto destroy
153 if (activityDelay_ms > 0)
154 element.timeout_ms = ctx.lamp.now + activityDelay_ms;
155
156 // increase element count
157 activeUiElements++;
158 return true;
159 }
160
168 template<bool shouldUpdateTimeout = true>
169 bool update_type_progress(const auto& ctx, const ElementType type, uint16_t desiredIndex, const uint8_t progress)
170 {
171 size_t index;
172 if (get_N_of_type(type, desiredIndex, index))
173 {
174 elements[index].progress = progress;
175
176 // if requested, update timeout
177 const uint32_t newTimeout = ctx.lamp.now + freezeSize * ctx.lamp.frameDurationMs;
178 if (shouldUpdateTimeout and elements[index].timeout_ms <= newTimeout)
179 {
180 // add two frames of breathing room
181 elements[index].timeout_ms = newTimeout;
182 }
183 return true;
184 }
185 return false;
186 }
187
195 template<bool shouldUpdateTimeout = true> bool update_type_color(const auto& ctx,
196 const ElementType type,
197 uint16_t desiredIndex,
198 const colors::PaletteTy& palette)
199 {
200 size_t index;
201 if (get_N_of_type(type, desiredIndex, index))
202 {
203 elements[index].color = palette;
204
205 // if requested, update timeout
206 const uint32_t newTimeout = ctx.lamp.now + freezeSize * ctx.lamp.frameDurationMs;
207 if (shouldUpdateTimeout and elements[index].timeout_ms <= newTimeout)
208 {
209 // add two frames of breathing room
210 elements[index].timeout_ms = newTimeout;
211 }
212 return true;
213 }
214 return false;
215 }
216
217 bool update_type_timeout(const auto& ctx, const ElementType type, uint16_t desiredIndex, const uint32_t timeout_ms)
218 {
219 size_t index;
220 if (get_N_of_type(type, desiredIndex, index))
221 {
222 // add two frames of breathing room
223 elements[index].timeout_ms = ctx.lamp.now + timeout_ms;
224 return true;
225 }
226 return false;
227 }
228
237 template<bool shouldUpdateTimeout = true> bool update_type(const auto& ctx,
238 const ElementType type,
239 uint16_t desiredIndex,
240 const uint8_t progress,
241 const colors::PaletteTy& palette)
242 {
243 size_t index;
244 if (get_N_of_type(type, desiredIndex, index))
245 {
246 elements[index].progress = progress;
247 elements[index].color = palette;
248
249 // if requested, update timeout
250 const uint32_t newTimeout = ctx.lamp.now + freezeSize * ctx.lamp.frameDurationMs;
251 if (shouldUpdateTimeout and elements[index].timeout_ms <= newTimeout)
252 {
253 // add two frames of breathing room
254 elements[index].timeout_ms = newTimeout;
255 }
256 return true;
257 }
258 return false;
259 }
260
261protected:
263 bool get_N_of_type(const ElementType type, uint16_t desiredIndex, size_t& elementId) const
264 {
265 // display all elements
266 for (uint8_t i = 0; i < activeUiElements; ++i)
267 {
268 // find elements of a type
269 if (elements[i].type == type)
270 {
271 // check that we reached the desired element
272 if (desiredIndex <= 0)
273 {
274 elementId = i;
275 return true;
276 }
277 // or decrement the element count
278 desiredIndex -= 1;
279 }
280 }
281 return false;
282 }
283
284 void drawElement(const __private::UIElement& e, auto& ctx) const
285 {
286 switch (e.type)
287 {
289 {
291 break;
292 }
293 case ElementType::DOT:
294 {
296 break;
297 }
298 case ElementType::NONE:
299 {
300 break;
301 }
302
303 // NO DEFAULT: so we have errors on compile
304 }
305 }
306
308 void display_ramp(auto& ctx,
309 const uint8_t progress,
310 const colors::PaletteTy& palette,
311 const uint16_t startCoordinateY) const
312 {
313 const uint16_t rampScale = (progress / 255.0) * ctx.lamp.maxWidth;
314 for (uint16_t i = 0; i < rampScale; ++i)
315 {
316 const auto color = modes::colors::from_palette<false>(lmpd_map<uint8_t>(i, 0, rampScale, 0, 255), palette);
317 ctx.lamp.setPixelColorXY(i, startCoordinateY, color);
318 }
319 }
320
322 void display_dot(auto& ctx,
323 const uint8_t progress,
324 const colors::PaletteTy& palette,
325 const uint16_t coordinateX,
326 const uint16_t coordinateY) const
327 {
328 const auto color = modes::colors::from_palette<false>(progress, palette);
329 ctx.lamp.setPixelColorXY(coordinateX, coordinateY, color);
330 }
331
332private:
334 std::array<__private::UIElement, UIElementSize> elements;
336 size_t activeUiElements = 0;
337};
338
339} // namespace overlay
340} // namespace lampda::modes::draw
341
342#endif
Definition: overlay.hpp:50
void display_dot(auto &ctx, const uint8_t progress, const colors::PaletteTy &palette, const uint16_t coordinateX, const uint16_t coordinateY) const
Display a single colored pixel.
Definition: overlay.hpp:322
bool add_ui_element(const auto &ctx, const ElementType type, const colors::PaletteTy &palette, const uint16_t coordinateX=0, const uint16_t coordinateY=0, const uint8_t progress=0, const uint32_t activityDelay_ms=50)
Add a new UI element to the overlay.
Definition: overlay.hpp:134
void display_ramp(auto &ctx, const uint8_t progress, const colors::PaletteTy &palette, const uint16_t startCoordinateY) const
Display a colored ramp.
Definition: overlay.hpp:308
uint8_t get_element_count(const ElementType type) const
Return the count of elements of a target type.
Definition: overlay.hpp:110
bool get_N_of_type(const ElementType type, uint16_t desiredIndex, size_t &elementId) const
Find and return the Nth element of a given type.
Definition: overlay.hpp:263
void clear()
Clear all UI elements.
Definition: overlay.hpp:107
bool update_type_color(const auto &ctx, const ElementType type, uint16_t desiredIndex, const colors::PaletteTy &palette)
Update the target UI element color palette.
Definition: overlay.hpp:195
bool update_type(const auto &ctx, const ElementType type, uint16_t desiredIndex, const uint8_t progress, const colors::PaletteTy &palette)
Update the target UI element.
Definition: overlay.hpp:237
bool update_type_progress(const auto &ctx, const ElementType type, uint16_t desiredIndex, const uint8_t progress)
Update the target UI element progress.
Definition: overlay.hpp:169
void display_update(auto &ctx)
Display and update the overlay.
Definition: overlay.hpp:57
std::array< uint32_t, 16 > PaletteTy
Palette types.
Definition: palettes.hpp:18
ElementType
< Define an UI element type
Definition: overlay.hpp:14
< define a display color
Definition: overlay.hpp:24
Define an UI element.
Definition: overlay.hpp:35
uint16_t coordinateY
start Y coordinates
Definition: overlay.hpp:40
ElementType type
type of UI elements
Definition: overlay.hpp:36
colors::PaletteTy color
color palette to display
Definition: overlay.hpp:42
uint16_t coordinateX
start X coordinates
Definition: overlay.hpp:39
int32_t timeout_ms
If set to a positive number, this element will delete itself at the set time.
Definition: overlay.hpp:44
uint8_t progress
0-255 animation progress
Definition: overlay.hpp:37