From 80f48a3b85feeff11a6151fdc179d776ce4e6566 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Mon, 30 Mar 2026 00:40:52 -0500 Subject: [PATCH] stock theme --- .../assets/components/tools/theme_maker.js | 58 +++++++++++++++---- starpilot/system/the_pond/the_pond.py | 37 +++++++----- 2 files changed, 72 insertions(+), 23 deletions(-) diff --git a/starpilot/system/the_pond/assets/components/tools/theme_maker.js b/starpilot/system/the_pond/assets/components/tools/theme_maker.js index 3cb5d927..488189aa 100644 --- a/starpilot/system/the_pond/assets/components/tools/theme_maker.js +++ b/starpilot/system/the_pond/assets/components/tools/theme_maker.js @@ -33,6 +33,15 @@ const SOUND_DEFINITIONS = [ { key: "startup", label: "Startup Sound" }, ]; +const BUILTIN_THEME_OPTIONS = { + colors: { name: "Stock", path: "__stock__", type: "stock", builtin: true }, + distance_icons: { name: "Stock", path: "__stock__", type: "stock", builtin: true }, + icons: { name: "Stock", path: "__stock__", type: "stock", builtin: true }, + sounds: { name: "Stock", path: "__stock__", type: "stock", builtin: true }, + steering_wheel: { name: "Stock", path: "__stock__", type: "stock", builtin: true }, + turn_signals: { name: "None (Stock)", path: "__stock_none__", type: "stock_none", builtin: true }, +}; + const fileStore = { images: { distanceIcons: {} }, sounds: {}, @@ -705,6 +714,19 @@ export function ThemeMaker() { state.showManageThemesModal = true; }; + const getVisibleThemesForActiveTab = () => { + const builtinTheme = BUILTIN_THEME_OPTIONS[state.activeTab]; + const visibleThemes = state.themes.filter(theme => { + if (state.activeTab === "steering_wheel") { + return theme.type === "steering_wheel" || (theme.type === "holiday" && theme.hasSteeringWheel); + } + const key = `has${state.activeTab.charAt(0).toUpperCase() + state.activeTab.slice(1).replace(/_([a-z])/g, g => g[1].toUpperCase())}`; + return theme[key]; + }); + + return builtinTheme ? [builtinTheme, ...visibleThemes] : visibleThemes; + }; + const mergeDownloadablesIntoThemes = () => { const byName = new Map(); const norm = (s) => (s || "") @@ -888,11 +910,12 @@ export function ThemeMaker() { } } - if (assetType === "steering_wheel" && theme.path) { + if (assetType === "steering_wheel" && data.images.steeringWheel?.path) { const url = `/api/themes/asset/${theme.path}/${data.images.steeringWheel.path}?type=${theme.type}`; const fileResponse = await fetch(url); const blob = await fileResponse.blob(); - const file = new File([blob], theme.path, { type: blob.type }); + const filename = data.images.steeringWheel.filename || theme.path; + const file = new File([blob], filename, { type: blob.type }); fileStore.images.steeringWheel = file; state.imageFileNames.steeringWheel = theme.name; } @@ -943,6 +966,26 @@ export function ThemeMaker() { } }; + const loadBuiltinTurnSignals = () => { + clearAssetType("turn_signals"); + state.themeSubmitted = false; + state.turnSignalLength = 100; + state.turnSignalType = "Single Image"; + state.turnSignalStyle = "Traditional"; + state.imageFileNames.turnSignal = "None"; + state.imageFileNames.turnSignalBlindspot = ""; + showSnackbar('Loaded stock turn signals.'); + }; + + const loadSelectableThemeAsset = async (theme, assetType) => { + if (theme?.type === "stock_none" && assetType === "turn_signals") { + loadBuiltinTurnSignals(); + return; + } + + await loadThemeAsset(theme, assetType); + }; + const confirmDelete = (theme) => { state.themeToDelete = theme; state.showDeleteConfirmModal = true; @@ -1370,16 +1413,11 @@ export function ThemeMaker() { `)}
- ${() => state.themes.filter(theme => { - if (state.activeTab === "steering_wheel") { - return theme.type === "steering_wheel" || (theme.type === "holiday" && theme.hasSteeringWheel); - } - const key = `has${state.activeTab.charAt(0).toUpperCase() + state.activeTab.slice(1).replace(/_([a-z])/g, g => g[1].toUpperCase())}`; - return theme[key]; - }).map(theme => html` -
+ ${() => getVisibleThemesForActiveTab().map(theme => html` +
${theme.name} ${theme.is_user_created ? " 🌟" : ""} ${() => { + if (theme.builtin) return ""; const key = `localHas${state.activeTab .replace(/_([a-z])/g, (_, c) => c.toUpperCase()) .replace(/^[a-z]/, c => c.toUpperCase())}`; diff --git a/starpilot/system/the_pond/the_pond.py b/starpilot/system/the_pond/the_pond.py index 5da6db0f..a72384b8 100644 --- a/starpilot/system/the_pond/the_pond.py +++ b/starpilot/system/the_pond/the_pond.py @@ -41,7 +41,7 @@ from panda import Panda from openpilot.starpilot.assets.theme_manager import HOLIDAY_THEME_PATH, THEME_COMPONENT_PARAMS from openpilot.starpilot.common.starpilot_utilities import delete_file, get_lock_status, run_cmd -from openpilot.starpilot.common.starpilot_variables import ACTIVE_THEME_PATH, ERROR_LOGS_PATH, EXCLUDED_KEYS, LEGACY_STARPILOT_PARAM_RENAMES, RESOURCES_REPO, SCREEN_RECORDINGS_PATH, THEME_SAVE_PATH,\ +from openpilot.starpilot.common.starpilot_variables import ACTIVE_THEME_PATH, ERROR_LOGS_PATH, EXCLUDED_KEYS, LEGACY_STARPILOT_PARAM_RENAMES, RESOURCES_REPO, SCREEN_RECORDINGS_PATH, STOCK_THEME_PATH, THEME_SAVE_PATH,\ default_ev_tuning_enabled, update_starpilot_toggles from openpilot.starpilot.common.testing_grounds import ( DEFAULT_TESTING_GROUND_VARIANT as SHARED_DEFAULT_TESTING_GROUND_VARIANT, @@ -4330,6 +4330,8 @@ def setup(app): if theme_type == "active" or theme == "__active__": file_path = ACTIVE_THEME_PATH / asset_path + elif theme_type == "stock" or theme == "__stock__": + file_path = STOCK_THEME_PATH / asset_path elif asset_path.startswith("steering_wheels/"): file_path = THEME_SAVE_PATH / asset_path elif asset_path.startswith("steering_wheel/") and "holiday" in theme_type: @@ -4548,7 +4550,10 @@ def setup(app): @app.route("/api/themes/load/") def load_theme(theme_path): theme_type = request.args.get("type", "") - theme_dir = HOLIDAY_THEME_PATH / theme_path if "holiday" in theme_type else THEME_SAVE_PATH / "theme_packs" / theme_path + if theme_type == "stock" or theme_path == "__stock__": + theme_dir = STOCK_THEME_PATH + else: + theme_dir = HOLIDAY_THEME_PATH / theme_path if "holiday" in theme_type else THEME_SAVE_PATH / "theme_packs" / theme_path response_data = { "colors": None, @@ -4567,16 +4572,15 @@ def setup(app): icons_dir = theme_dir / "icons" if icons_dir.exists(): - if (icons_dir / "button_home.gif").exists(): - response_data["images"]["homeButton"] = { - "filename": "button_home.gif", - "path": "icons/button_home.gif" - } - if (icons_dir / "button_settings.png").exists(): - response_data["images"]["settingsButton"] = { - "filename": "button_settings.png", - "path": "icons/button_settings.png" - } + for base_name, response_key in [("button_home", "homeButton"), ("button_settings", "settingsButton")]: + for ext in [".gif", ".png", ".jpg", ".jpeg"]: + filename = f"{base_name}{ext}" + if (icons_dir / filename).exists(): + response_data["images"][response_key] = { + "filename": filename, + "path": f"icons/{filename}" + } + break distance_dir = theme_dir / "distance_icons" if distance_dir.exists(): @@ -4642,7 +4646,14 @@ def setup(app): } steering_wheel_path = None - if "holiday" in theme_type: + if theme_type == "stock" or theme_path == "__stock__": + steering_dir = theme_dir / "steering_wheel" + if steering_dir.exists() and steering_dir.is_dir(): + for file in steering_dir.iterdir(): + if file.is_file() and file.suffix.lower() in [".png", ".jpg", ".jpeg", ".gif"]: + steering_wheel_path = f"steering_wheel/{file.name}" + break + elif "holiday" in theme_type: steering_dir = theme_dir / "steering_wheel" if steering_dir.exists() and steering_dir.is_dir(): for file in steering_dir.iterdir():