Skip to content

ui: unified theme selector with seasonal scene packs + animated scenes (C3X + C4) - #162

Open
ghbarker wants to merge 1 commit into
BluePilotDev:bp-devfrom
ghbarker:unified-theme-selector
Open

ui: unified theme selector with seasonal scene packs + animated scenes (C3X + C4)#162
ghbarker wants to merge 1 commit into
BluePilotDev:bp-devfrom
ghbarker:unified-theme-selector

Conversation

@ghbarker

@ghbarker ghbarker commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

The evidence that motivated this

  • Theme features had grown device-split and inconsistent: the 8-Bit Racer theme, wheel art, and colors each had their own toggles, and the comma four had no seasonal theming at all.
  • The C3X theme dropdown had a real bug: the dialog callback read the DialogResult enum as if it were the selected label, so every selection saved "Off" regardless of what was highlighted.
  • Adding a holiday look required code changes per theme — nothing a user could drop in.

Why the fix is shaped this way

  • One selector, one param, both devices. BPThemePack picks the active pack; theme_pack.selector_entries() is the single source of truth the C3X page, the MICI page, and sunnylink all read — so the menus can never disagree. Packs are listed in calendar order of their season windows (Jan→Dec), with Off and 8-Bit Racer pinned first.
  • Packs are asset-only. A theme is a directory (colors.json, wheel.png, sounds, scene.json, season.json) — bundled or dropped onto the device over SSH; no code per theme. BPThemeAutoSeasonal lets packs activate themselves inside their own declared date windows (fixed dates or movable feasts — Easter, Thanksgiving).
  • One modular scene architecture (theme_scene.py): every renderer draws through a single active_scene() accessor, so there is no per-renderer theme logic to keep in sync; the animated layers (snow, string lights, bats, the NYE ball drop) are procedural — zero image assets for scenery.
  • The C3X selector callback now follows the same DialogResult pattern as every other dialog in the file.

The evidence afterwards

  • 25 theme tests green: every bundled pack's scene parses and renders, and every season window resolves (including the anchored movable feasts).
  • The selector fix verified against the widget contract; MICI shares the same entries list, so both devices show the identical, calendar-ordered menu.

What each change is

  • selfdrive/ui/bp/lib/theme_pack.py: pack discovery, season windows, calendar-ordered selector_entries().
  • selfdrive/ui/bp/lib/theme_scene.py + renderer hookups (both devices): the scene architecture.
  • selfdrive/assets/bp_themes/: eleven packs, each with colors, wheel art, scene, season window.
  • Settings pages (C3X + MICI) + sunnylink: the unified Theme selector and Auto Seasonal toggle; the C3X dialog-callback fix.
  • selfdrive/ui/soundd.py: per-pack sound overrides.

Test it yourself

  • Settings → visuals: pick a pack and watch the onroad scene, colors, and wheel change live (no restart); toggle Auto Seasonal and the active pack follows the date.
  • .

Risks / limits

  • Default is no pack selected → stock look; nothing changes until you pick one. Opt-in, UI-only; no effect on control.
  • Assets are stored directly in git (.gitattributes opts bp_themes/** out of LFS).

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

@ghbarker
ghbarker force-pushed the unified-theme-selector branch 4 times, most recently from 496e730 to 8a4b8a4 Compare July 27, 2026 02:35
…s (C3X + C4)

One theme system for both devices: a single selector param (BPThemePack) drives
per-pack colors, steering-wheel art, and layered onroad scenes (static + animated),
with an optional auto-seasonal mode where each pack declares its own date window.

- selfdrive/ui/bp/lib/theme_pack.py — pack resolution + param plumbing.
- selfdrive/ui/bp/lib/theme_scene.py + theme_scene_assets.py — the scene architecture:
  modular static/animated layers, one active_scene() the renderers draw through.
- Renderers (mici + c3x augmented road view / cameraview / model / hud / torque /
  chevron / exp button) draw the active scene via that shared accessor — no per-file
  theme logic.
- selfdrive/assets/bp_themes/** — eleven packs (holidays + seasonal), stored directly
  in git (see .gitattributes); soundd.py — per-pack sounds.
- Params BPThemePack + BPThemeAutoSeasonal; on-device selector + sunnylink.
- Tests: test_theme_scene.py, test_theme_seasonal.py.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Selector lists packs in calendar order of their season windows (8-Bit Racer
stays the default entry); fixes the C3X theme dialog saving "Off" regardless
of selection (callback read the DialogResult enum as the label).
@ghbarker
ghbarker force-pushed the unified-theme-selector branch from 8a4b8a4 to b430c82 Compare July 30, 2026 03:52
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