4.2. Visual aids — tutorial-mode overlays, mouse trail, narration, key HUD
Tutorial-mode overlays — highlight rectangles, mouse-cursor sprite + trail,
narration text, key HUD, click flash — painted over the live ImGui surface to
guide the viewer through scripted recordings. Every overlay is opt-in and
keyed off the boost registry’s widget path, so highlighting
MAIN_WIN/SETTINGS_TAB/RPS resolves to the exact rect the renderer drew.
Painters are registered as end-of-frame hooks so the host’s render loop is
unchanged.
Auto-highlight (imgui_auto_highlight_on_command) makes every accepted
imgui_* command auto-flash its target — useful when recording with
imgui_playwright so each programmatic action is visually narrated
without explicit imgui_highlight calls.
4.2.1. Constants
- g_keycap_trace_max = 6
g_keycap_trace_max:int const
- g_keycap_trace_fallback_lifetime_s = 1f
g_keycap_trace_fallback_lifetime_s:float const
4.2.2. Structures
- HighlightArgs
struct HighlightArgs
- MouseTrailArgs
struct MouseTrailArgs
- NarrateArgs
struct NarrateArgs
- AutoHighlightArgs
struct AutoHighlightArgs
- CursorSpriteArgs
struct CursorSpriteArgs
- KeyHudArgs
struct KeyHudArgs
- FocusRectArgs
struct FocusRectArgs
- MemDebugArgs
struct MemDebugArgs
4.2.3. Highlight overlay
- highlight(target: string; frames: int = highlight_default_frames; color: uint = highlight_color )
Flash a colored rect around the named widget’s bbox for frames ticks. target is a registry path or "0x<hex_id>".
- Arguments:
target : string
frames : int
color : uint
- imgui_auto_highlight(input: JsonValue? ): JsonValue?
[live_command] toggle for the imgui_auto_highlight_on_command flag. Arg: enabled.
- Arguments:
input : JsonValue?
- imgui_highlight(input: JsonValue? ): JsonValue?
[live_command] wrapper around highlight. Args: target, frames, color.
- Arguments:
input : JsonValue?
4.2.4. Mouse trail
- imgui_mouse_trail(input: JsonValue? ): JsonValue?
[live_command] wrapper around mouse_trail. Args: enabled, fade, color.
- Arguments:
input : JsonValue?
- mouse_trail(enabled: bool; fade: float = -1f; color: uint = 0x0 )
Toggle the fading mouse-trail overlay; non-default fade / color override the module globals. Disabling clears the trail buffer.
- Arguments:
enabled : bool
fade : float
color : uint
4.2.5. Narration
- compute_connector_end(target_bbox: float4; banner_center: float2 ): float2
Mirror of compute_connector_start on the target side: closest
point on the target’s bbox boundary to banner_center. Same
clamp-onto-rect trick — terminates the line on the target’s edge (or
corner, in offset cases) instead of inside it.
- Arguments:
target_bbox : float4
banner_center : float2
- compute_connector_start(anchor: float2; box_size: float2; widget_center: float2 ): float2
Closest point on the post-it’s boundary to widget_center. Coincides
with the corresponding edge midpoint when widget_center is directly
outside one side of the post-it; for offset/corner cases (post-it
viewport-clamped sideways relative to the target), the line walks to
the nearest corner so the arrow points naturally at the target.
- Arguments:
anchor : float2
box_size : float2
widget_center : float2
- compute_narrate_anchor(has_target: bool; widget_bbox: float4; box_size: float2; viewport: float2; edge_margin: float; gap: float; shadow: float2; hud_zone_h: float; other_bboxes: array<float4>; avoid_bboxes: array<float4> ): float2
Pick a post-it anchor (top-left corner) by scoring 4 viewport-clamped
candidates (right/left/below/above). score_anchor adds 1 per incidental
widget bbox (other_bboxes) the banner overlaps, and 1000 if it overlaps
the anchor target OR any avoid_bboxes member (the step’s other “main”
elements) — so a multi-target step’s box never covers a related control —
lowest-score candidate wins, ties broken by iteration order (right >
left > below > above). If the banner is larger than the viewport’s
placement region even when clamped, returns a bottom-left safety
anchor — only fires when the caller passed text that genuinely cannot
fit.
- Arguments:
has_target : bool
widget_bbox : float4
box_size : float2
viewport : float2
edge_margin : float
gap : float
shadow : float2
hud_zone_h : float
other_bboxes : array<float4>
avoid_bboxes : array<float4>
- imgui_narrate(input: JsonValue? ): JsonValue?
[live_command] wrapper around narrate.
Args: text, target (single anchor) OR targets (list — first is the anchor, all
hard-avoided), frames, duration_s (wall-clock seconds; wins over frames).
- Arguments:
input : JsonValue?
4.2.5.1. narrate
- narrate(text: string; target: string = ""; frames: int = narrate_default_frames; duration_s: float = -1f )
Pop a callout box with text. By default it lingers frames render ticks; pass
duration_s > 0 to hold it for that many wall-clock seconds instead — rate-independent,
required for recordings where render fps and capture fps diverge. If target resolves
to a widget bbox the box anchors next to it with a connector line; otherwise it floats top-left.
- Arguments:
text : string
target : string
frames : int
duration_s : float
- narrate(text: string; targets: array<string>; frames: int = narrate_default_frames; duration_s: float = -1f )
4.2.6. HUD
- imgui_focus_rect(input: JsonValue? ): JsonValue?
[live_command] toggle for the focus rectangle around io.active_widget — shows where typing lands. Arg: enabled.
- Arguments:
input : JsonValue?
- imgui_key_hud(input: JsonValue? ): JsonValue?
[live_command] toggle for the bottom-center keycap HUD + Ctrl/Shift/Alt/Cmd modifier strip. Args: enabled, show_modifiers, keycap_fade_s (seconds a keycap lingers - bump it so a chord stays readable while a voice line names it).
- Arguments:
input : JsonValue?
4.2.7. Cursor sprite
- cursor_sprite(enabled: bool )
Toggle the in-frame cursor sprite. Drawn on the ForegroundDrawList so APNG recordings show a visible pointer even when the OS hardware cursor isn’t captured.
- Arguments:
enabled : bool
- imgui_cursor_sprite(input: JsonValue? ): JsonValue?
[live_command] wrapper around cursor_sprite. Arg: enabled.
- Arguments:
input : JsonValue?
4.2.8. Override hooks
- apply_synth_io_override()
Per-frame synth IO entry point for hand-rolled (non-harness) update loops — call between the
backend’s *_NewFrame() and ImGui’s NewFrame(). Drains the COMPLETE synth pipeline:
advances L1 input coroutines (imgui_click press/release) then drives
imgui_synth_tick (timelines +
held-state re-assert). Mirrors the harness’s advance_coroutines() (in harness_begin_frame)
+ imgui_synth_tick() (in harness_new_frame), so coroutine-based synth clicks work
without the harness — a demo calls this one function and never needs advance_coroutines itself.
4.2.9. Memory debugging
- imgui_memory_debug(input: JsonValue? ): JsonValue?
[live_command] toggle for imgui_debug_memory — per-frame GC-pressure logging. Arg: enabled.
- Arguments:
input : JsonValue?
4.2.10. Color utilities
- rgba(r: int; g: int; b: int; a: int ): uint
Pack R/G/B/A bytes into ImGui’s IM_COL32 word order. Useful when configuring the tunable color globals by channel rather than hex literal.
- Arguments:
r : int
g : int
b : int
a : int
4.2.11. Serve / lifecycle
- visual_aids_init()
[init] — registers the foreground-drawlist paint hook and the post-command auto-highlight hook. Runs once at module load.