Skip to content

ui: unified theme selector with seasonal scene packs (C3X + C4)#159

Closed
ghbarker wants to merge 2 commits into
BluePilotDev:bp-devfrom
ghbarker:unified-theme-selector
Closed

ui: unified theme selector with seasonal scene packs (C3X + C4)#159
ghbarker wants to merge 2 commits into
BluePilotDev:bp-devfrom
ghbarker:unified-theme-selector

Conversation

@ghbarker

@ghbarker ghbarker commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

What this adds

A single Theme selector (Settings → Visuals) on both the comma 3X and comma four UIs, driven by one BPThemePack param and one shared entry list — so theming is selected the same way on both devices. The selector carries:

  • Off (stock UI)
  • 8-Bit Racer — the existing theme, absorbed into the selector (its separate toggle is removed)
  • Ten seasonal packs: New Year's, Valentine's, St. Patrick's, April Fools, Easter, Cinco de Mayo, Fourth of July, Halloween, Thanksgiving, Christmas

Theme packs are asset-only

<pack_name>/
  colors/colors.json        # Path, PathEdge, LaneLines, LeadMarker, RoadEdges, Accent, Background — all optional
  sounds/<name>.wav         # optional alert-sound overrides by filename (mono 16-bit 48 kHz)
  steering_wheel/wheel.png  # optional wheel icon

New themes need zero code. Users can also drop packs into /data/bp_themes/ over SSH — discovered automatically, same-name user packs shadow bundled ones. Everything degrades gracefully: a malformed wav falls back to the stock sound, a missing color key keeps the stock color.

Themed views render as full scenes

v2 — animated + static scene layers. Each pack may ship a scene.json consumed by one
shared scene engine (theme_scene.py): particle layers (falling snow, rising hearts,
tumbling leaves, fluttering bats, firework bursts), static decor (string lights with
catenary droop, berry garlands, flag bunting, a carved pumpkin) and a sky treatment —
full strength in Minimal Driving View, subtle over the live camera, alerts always on
top. Sprites are procedurally rendered signed-distance fields, so the PR contains no
new image assets
: every snowflake, heart and bat below is generated from math at load
time and tinted per particle. The scene architecture is one modular interface
(SceneBase with background/foreground passes + capability flags); 8-Bit Racer now
rides the same dispatch through a capability adapter with its drawing untouched, and a
pack without scene.json renders exactly as before. Budgets are hard-capped and
validated — a malformed user scene.json degrades to colors-only. 24 new tests.

  • Background paints a sky gradient behind the road whenever Minimal Driving View hides the camera
  • The path ribbon runs a full-strength gradient (PathEdge near → Path far)
  • Lane lines and road edges use the wider minimal-view geometry with a stronger glow halo
  • Accent tints the torque-bar fill (the high-torque yellow→orange warning blend is preserved) and the MICI set-speed value
  • The vision-lead chevron and its info box follow LeadMarker (radar leads stay blue)

UI details

  • C3X: the Theme row opens a scrollable option dialog (same pattern as the preferred-network picker), so any number of packs fits.
  • MICI: a cycling toggle built from the same entries; its indicator pills auto-compress.
  • soundd hot-reloads sounds when the selection changes (only while no alert is playing).

Assets

Bundled palettes are original. Steering-wheel icons are from OpenMoji (CC BY-SA 4.0, credited in selfdrive/assets/bp_themes/README.md). Total asset weight ~2.5 MB, stored as regular git blobs (exempted from LFS in .gitattributes, matching the existing BP asset pattern).

Testing

  • Selector state logic (Off / 8-Bit Racer / pack, case-insensitivity, unknown-pack fallback) verified via script on this exact commit
  • Both UI layouts boot clean with a pack active (WSL, replay environment)
  • scons builds after the BPThemePack params key addition
  • Pack integrity check: all ten packs load colors + wheel icon

Screenshots

Captured on the PC preview (replay of a real drive, Minimal Driving View). Theme switching is live — no restart between these. Everything you see beyond the road — the falling snow, string lights, garlands, leaves, bats, the pumpkin — is procedural: zero image assets in the diff.

Halloween

halloween

Christmas

christmas

8-Bit Racer (same selector)

rad racer

new years New Year's valentines Valentine's
st patricks St. Patrick's april fools April Fools
easter Easter cinco Cinco de Mayo
july4 Fourth of July thanksgiving Thanksgiving
comma four (MICI) layout

halloween mici

🤖 Generated with Claude Code

Adds a single Theme selector (Settings -> Visuals) to the C3X and comma
four UIs, driven by one BPThemePack param and one shared entry list, so
theming behaves identically on both devices. The selector carries Off,
the existing 8-Bit Racer theme (its separate toggle is absorbed), and
ten bundled seasonal packs covering New Year's through Christmas.

A pack is a directory of plain assets - no code:
  colors/colors.json        Path, PathEdge, LaneLines, LeadMarker,
                            RoadEdges, Accent, Background (all optional)
  sounds/<name>.wav         alert-sound overrides by filename
  steering_wheel/wheel.png  wheel icon override

Themed views render as full scenes: Background paints a sky gradient
whenever Minimal Driving View hides the camera, the path ribbon runs a
full-strength gradient, lane lines and road edges use the wider
minimal-view geometry with a stronger glow halo, the torque-bar fill
and set-speed value take the Accent color, and the vision-lead chevron
and info box follow LeadMarker.

The C3X page selects via a scrollable option dialog and the MICI page
via a cycling toggle - both built from the same entries, so any number
of packs stays inside the widget. Users can drop additional packs into
/data/bp_themes over SSH; malformed pieces degrade gracefully to stock
(bad wavs fall back to stock sounds, missing colors keep stock colors).

Bundled palettes are original; wheel icons are from OpenMoji
(CC BY-SA 4.0, credited in the README).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ghbarker
ghbarker force-pushed the unified-theme-selector branch from 3f2aea1 to 55d3ec6 Compare July 22, 2026 07:35
…ecture

Builds on the theme selector: a SceneBase interface (background pass before the
model render, foreground pass under alerts, replaces_road/replaces_hud
capability flags) unifies every theme kind. Rad Racer participates through a
capability adapter — its drawing is untouched, the ad-hoc dispatch checks are
gone. Seasonal packs get data-driven scenes from a per-pack scene.json:
particle layers (falling snow, rising hearts, tumbling leaves, fluttering
bats, firework bursts), static decor (string lights, garlands, bunting,
corner pieces) and a sky treatment — full strength in Minimal Driving View,
subtle over the live camera, alerts always on top. Sprites are procedurally
rendered signed-distance fields (no bundled images), tinted per particle at
draw time. Budgets are hard-capped and validated; a pack without scene.json
is colors-only, exactly as before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ghbarker
ghbarker force-pushed the unified-theme-selector branch from 55d3ec6 to 61886fb Compare July 22, 2026 07:40
ghbarker added a commit to ghbarker/openpilot that referenced this pull request Jul 22, 2026
…garlands, leaves, bats, fireworks, bunting)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ghbarker

Copy link
Copy Markdown
Contributor Author

Superseded by a fresh PR with the v2 scene system and updated screenshots — same branch, clean two-commit history (original selector + scenes). New PR follows momentarily.

@ghbarker ghbarker closed this Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant