feat: HUD polish — annunciators, adaptive numpad, STATUSTEXT ticker#75
feat: HUD polish — annunciators, adaptive numpad, STATUSTEXT ticker#75
Conversation
3a0b830 to
9226906
Compare
There was a problem hiding this comment.
Pull request overview
This PR bundles HUD visual/UX improvements for both Console and Tactical modes, including STATUSTEXT-driven notifications, adaptive layouts, and new micro-animations (“annunciators”) tied to replay events.
Changes:
- Added STATUSTEXT capture from ULog
Lmessages, exposed via playback state and rendered as a severity-colored ticker/notification panel. - Introduced Tactical HUD rendering (new module) plus ortho inset drawing helper and updated correlation line coloring.
- Improved multi-drone replay UX: adaptive numpad sizing, multi-drone marker/timeline rendering, global marker cycling, and trail/marker coloring updates.
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| CMakeLists.txt | Builds new Tactical HUD + annunciator modules. |
| src/main.c | Integrates HUD mode cycling, STATUSTEXT feeding, marker sync/cycling, multi-drone trail defaults. |
| src/hud.h | Adds HUD modes, STATUSTEXT ticker storage, notification toggle, annunciator state, multi-drone marker inputs. |
| src/hud.c | Implements STATUSTEXT ticker rendering/feeding, adaptive numpad, annunciator-driven effects, font scaling floors. |
| src/hud_transport.h | Extends transport API to accept per-drone marker arrays. |
| src/hud_transport.c | Renders multi-drone markers on timeline, uses ID-trails color override via drone color. |
| src/hud_telemetry.h | Passes selected index for (future) telemetry annunciators. |
| src/hud_telemetry.c | Telemetry rendering refactors in support of upcoming peak-scale behavior. |
| src/hud_annunciators.h | New annunciator API/types for HUD micro-animations. |
| src/hud_annunciators.c | Implements annunciator timers, triggers, and query helpers. |
| src/tactical_hud.h | Declares Tactical HUD draw entrypoint. |
| src/tactical_hud.c | New Tactical HUD renderer: radar, gimbal rings, insets, ticker/notifications, reticle, stacks. |
| src/ortho_panel.h | Adds ortho_panel_draw_single() for tactical insets. |
| src/ortho_panel.c | Updates correlation line coloring + adds inset ortho drawing implementation. |
| src/vehicle.h | Extends marker drawing/color APIs with drone_color parameter for ID trails. |
| src/vehicle.c | Implements ID-trails marker coloring and passes drone_color through marker draw paths. |
| src/replay_markers.h | Adds global marker cycle API. |
| src/replay_markers.c | Implements global marker cycling across drones + chase camera restore behavior. |
| src/replay_trail.c | Adjusts sys-marker resolution to playback-time space using offsets. |
| src/ui_marker_input.h | Tracks drone index for label input targeting in multi-drone replays. |
| src/ulog_parser.h | Adds logging-message struct + callback API for L messages. |
| src/ulog_parser.c | Invokes logging callback when parsing ULog logging messages. |
| src/ulog_replay.h | Adds STATUSTEXT ring buffer types and per-replay storage. |
| src/ulog_replay.c | Hooks logging callback into replay init to capture STATUSTEXT. |
| src/data_source.h | Exposes STATUSTEXT ring pointer via playback_state_t. |
| src/data_source_ulog.c | Wires replay STATUSTEXT ring into playback state. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Peak scale: returns font scale factor (1.0 normal, 1.05 at peak) | ||
| float annunc_peak_scale_factor(const hud_annunciators_t *a, int drone_idx, int channel) { | ||
| if (drone_idx < 0 || drone_idx >= ANNUNC_MAX_VEHICLES) return 1.0f; | ||
| if (channel < 0 || channel >= ANNUNC_PEAK_CHANNELS) return 1.0f; | ||
| return a->peak_scale.at_peak[drone_idx][channel] ? 1.10f : 1.0f; | ||
| } |
There was a problem hiding this comment.
annunc_peak_scale_factor() returns 1.10f when at peak, but the comment says “1.05 at peak”. Please align the implementation and the documented behavior (either change the factor or update the comment) to avoid confusion when tuning HUD animation.
| int sel = lay->selected; | ||
|
|
There was a problem hiding this comment.
sel is assigned from lay->selected but never used, which will trigger an unused-variable warning under typical warning levels. Either use it (e.g., when applying peak-scale per selected drone) or remove the variable / mark it unused.
| int sel = lay->selected; |
| // Center solid, edges fade to transparent | ||
| float bg_x = tx - bg_pad; | ||
| float bg_w = total_w + bg_pad * 2; | ||
| float bg_h = msg_w.y + 4 * s; | ||
| float edge = bg_pad; | ||
| // Left fade | ||
| for (int px = 0; px < (int)edge; px++) { | ||
| float a = (float)px / edge; | ||
| Color fc = {bg_c.r, bg_c.g, bg_c.b, (unsigned char)(bg_c.a * a)}; | ||
| DrawRectangle((int)(bg_x + px), (int)ty, 1, (int)bg_h, fc); | ||
| } | ||
| // Center solid | ||
| DrawRectangle((int)(bg_x + edge), (int)ty, (int)(bg_w - edge * 2), (int)bg_h, bg_c); | ||
| // Right fade | ||
| for (int px = 0; px < (int)edge; px++) { | ||
| float a = 1.0f - (float)px / edge; | ||
| Color fc = {bg_c.r, bg_c.g, bg_c.b, (unsigned char)(bg_c.a * a)}; | ||
| DrawRectangle((int)(bg_x + bg_w - edge + px), (int)ty, 1, (int)bg_h, fc); | ||
| } |
There was a problem hiding this comment.
Ticker background rendering uses two per-pixel loops (for (px=0; px<edge; px++)) for every ticker line, every frame. On large windows (high s) this becomes a noticeable CPU cost. Consider replacing the per-pixel fades with a small precomputed gradient texture, DrawRectangleGradientEx, or a fixed small number of wider quads.
| // Center solid, edges fade to transparent | |
| float bg_x = tx - bg_pad; | |
| float bg_w = total_w + bg_pad * 2; | |
| float bg_h = msg_w.y + 4 * s; | |
| float edge = bg_pad; | |
| // Left fade | |
| for (int px = 0; px < (int)edge; px++) { | |
| float a = (float)px / edge; | |
| Color fc = {bg_c.r, bg_c.g, bg_c.b, (unsigned char)(bg_c.a * a)}; | |
| DrawRectangle((int)(bg_x + px), (int)ty, 1, (int)bg_h, fc); | |
| } | |
| // Center solid | |
| DrawRectangle((int)(bg_x + edge), (int)ty, (int)(bg_w - edge * 2), (int)bg_h, bg_c); | |
| // Right fade | |
| for (int px = 0; px < (int)edge; px++) { | |
| float a = 1.0f - (float)px / edge; | |
| Color fc = {bg_c.r, bg_c.g, bg_c.b, (unsigned char)(bg_c.a * a)}; | |
| DrawRectangle((int)(bg_x + bg_w - edge + px), (int)ty, 1, (int)bg_h, fc); | |
| } | |
| Color bg_transparent = (Color){sc.r, sc.g, sc.b, 0}; | |
| // Center solid, edges fade to transparent | |
| float bg_x = tx - bg_pad; | |
| float bg_w = total_w + bg_pad * 2; | |
| float bg_h = msg_w.y + 4 * s; | |
| float edge = bg_pad; | |
| // Left fade | |
| DrawRectangleGradientEx( | |
| (Rectangle){bg_x, ty, edge, bg_h}, | |
| bg_transparent, bg_c, bg_c, bg_transparent | |
| ); | |
| // Center solid | |
| DrawRectangle((int)(bg_x + edge), (int)ty, (int)(bg_w - edge * 2), (int)bg_h, bg_c); | |
| // Right fade | |
| DrawRectangleGradientEx( | |
| (Rectangle){bg_x + bg_w - edge, ty, edge, bg_h}, | |
| bg_c, bg_transparent, bg_transparent, bg_c | |
| ); |
| if ((char)msg_type == ULOG_MSG_LOGGING && p->logging_cb && msg_size >= 9) { | ||
| ulog_logging_msg_t lmsg; | ||
| lmsg.log_level = p->read_buf[0]; | ||
| memcpy(&lmsg.timestamp, p->read_buf + 1, 8); | ||
| lmsg.text = (const char *)(p->read_buf + 9); | ||
| lmsg.text_len = msg_size - 9; | ||
| p->logging_cb(&lmsg, p->logging_userdata); | ||
| } |
There was a problem hiding this comment.
New logging-message callback path in ulog_parser_next() isn’t covered by existing tests (current suite exercises open/seek/iterate but never sets ulog_parser_set_logging_callback() and asserts callbacks fire / text is handled correctly). Please add a unit test using a fixture known to contain ULOG_MSG_LOGGING messages (e.g., the 1040ff85...ulg fixture in tests/fixtures) to validate severity/timestamp/text parsing and callback invocation order.
- Parse ULog logging messages ('L' type) into per-drone ring buffer
- Color-coded STATUSTEXT ticker (N key toggle): severity colors from
theme drone palette, gradient-faded edges, persists until pushed out
- Console: warnings take over ticker zone above HUD bar
- Tactical: warnings show in bottom-right notification panel
- Adaptive numpad: 3x3 (≤9), 3x4 (10-12), 4x4 (13-16) with smaller
font for two-digit numbers
- Font scaling floors: minimum readable sizes at small windows,
label alpha reduced for better contrast
- Interpolation toast: I key now shows toast instead of printf
- Annunciator system (hud_annunciators.c/h):
- Console tab fade: per-drone color bar double-pulses on marker crossing
- Gimbal ring bounce: pinned drone cell bounces on marker (tactical)
- Radar droplet wave: two expanding rings from drone blip (tactical)
- Ticker warning flash: background brightens, text inverts on arrival
- Ring shake: gimbal cell oscillates on STATUSTEXT warning (tactical)
9226906 to
9a33901
Compare
- ulog_replay: move STATUSTEXT logging callback registration to after pre-scan rewind so the ring only fills with messages encountered during playback, not during the full-file pre-scan pass. - vehicle.h: drop stale "or multi-drone mode" from vehicle_marker_color docstring (multi_drone parameter was removed earlier in this PR). - hud_annunciators: remove unused peak_scale annunciator — struct, init loop, annunc_peak_update, annunc_peak_scale_factor, the PEAK_* channel defines, and the two call sites in main.c. Feature was abandoned; code was dead (factor function never called). - hud: bound severity ASCII→numeric conversion to '0'-'7' to avoid mis-handling corrupt or out-of-range severity bytes. - ortho_panel_draw_single: use pinned drone's color for correlation line instead of blended midpoint, matching ortho_panel_draw and ortho_draw_fullscreen_2d (the other two 2D ortho draw functions).
Summary
Bundle of HUD visual improvements: event-driven micro-animations, ULog warning message parsing, responsive layout, and quality-of-life fixes.
data_source.playback.statustexthud_annunciators.c/h):Blocked by
Test plan