From bd687f353fa3a87303a41cab42f219ebe91fc402 Mon Sep 17 00:00:00 2001 From: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Date: Fri, 29 May 2026 03:21:00 -0400 Subject: [PATCH] BigUI WIP: Sine Bonis P1 --- .../layouts/settings/starpilot/aethergrid.py | 28 +- .../layouts/settings/starpilot/main_panel.py | 18 +- .../ui/layouts/settings/starpilot/scribble.py | 332 ++++++++++++++++++ 3 files changed, 364 insertions(+), 14 deletions(-) create mode 100644 selfdrive/ui/layouts/settings/starpilot/scribble.py diff --git a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py index 603faf6be..5636a96f5 100644 --- a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py +++ b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py @@ -11,6 +11,7 @@ from openpilot.system.ui.lib.text_measure import measure_text_cached from openpilot.system.ui.widgets import Widget, DialogResult from openpilot.system.ui.widgets.label import gui_label from openpilot.selfdrive.ui.layouts.settings.starpilot.asset_loader import starpilot_texture +from openpilot.selfdrive.ui.layouts.settings.starpilot.scribble import draw_custom_icon GEOMETRY_OFFSET = 10 @@ -2338,6 +2339,9 @@ class AetherTile(Widget): "desc_bottom": desc_y + desc_block, } + def _draw_custom_icon(self, key: str, x: float, y: float, s: float, color: rl.Color): + draw_custom_icon(key, x, y, s, color) + def _render_tile_stack( self, face: rl.Rectangle, @@ -2352,6 +2356,7 @@ class AetherTile(Widget): title_size: int, primary_size: int, desc_size: int = 18, + custom_icon_key: str | None = None, ): content_pad = SPACING.tile_content max_w = face.width - (content_pad * 2) @@ -2360,8 +2365,14 @@ class AetherTile(Widget): primary_size = max(18, int(round(primary_size * scale))) desc_size = max(14, int(round(desc_size * scale))) title_lines = self._wrap_text(title_font, title, max_w, title_size, max_lines=2) - icon_scale = min(0.80, max(0.56, scale * 0.72)) if icon else 0.0 - icon_height = (icon.height * icon_scale) if icon else 0.0 + has_icon = (icon is not None) or (custom_icon_key is not None) + icon_scale = min(0.80, max(0.56, scale * 0.72)) if has_icon else 0.0 + if custom_icon_key: + icon_height = 100.0 * icon_scale + elif icon: + icon_height = icon.height * icon_scale + else: + icon_height = 0.0 desc_lines = self._wrap_text(desc_font, desc, max_w, desc_size, max_lines=3) if desc else [] layout = self._measure_tile_stack( face, @@ -2373,7 +2384,11 @@ class AetherTile(Widget): desc_size=desc_size, ) - if icon: + if custom_icon_key: + icon_width = 100.0 * icon_scale + icon_x = face.x + (face.width - icon_width) / 2 + self._draw_custom_icon(custom_icon_key, icon_x, layout["top"], icon_scale * 1.6667, rl.WHITE) + elif icon: icon_width = icon.width * icon_scale icon_x = face.x + (face.width - icon_width) / 2 rl.draw_texture_pro( @@ -2440,8 +2455,12 @@ class HubTile(AetherTile): self.get_status = get_status self.title = title self.desc = desc + self.custom_icon_key = None if icon_path: - if starpilot_icon: + if icon_path in ["sound", "steering", "navigate", "system", "display", "vehicle"]: + self.custom_icon_key = icon_path + self._icon = None + elif starpilot_icon: self._icon = starpilot_texture(icon_path, 100, 100) else: self._icon = gui_app.texture(icon_path, 100, 100) @@ -2482,6 +2501,7 @@ class HubTile(AetherTile): desc_font=self._font_desc, title_size=30, primary_size=18, + custom_icon_key=self.custom_icon_key, ) diff --git a/selfdrive/ui/layouts/settings/starpilot/main_panel.py b/selfdrive/ui/layouts/settings/starpilot/main_panel.py index ddd4f5d2e..5a7a8dc88 100644 --- a/selfdrive/ui/layouts/settings/starpilot/main_panel.py +++ b/selfdrive/ui/layouts/settings/starpilot/main_panel.py @@ -19,43 +19,41 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.vehicle import StarPilotV from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid, HubTile, RadioTileGroup, SPACING -STARPILOT_ICONS_DIR = "toggle_icons" - class StarPilotLayout(Widget): CATEGORIES = [ { "title": "Alerts & Sounds", - "icon": "icon_sound.png", + "icon": "sound", "panel": "SOUNDS", "color": "#E63956", }, { "title": "Driving Controls", - "icon": "icon_steering.png", + "icon": "steering", "buttons": [("DRIVING MODEL", "DRIVING_MODEL"), ("GAS / BRAKE", "LONGITUDINAL"), ("STEERING", "LATERAL")], "color": "#3B82F6", }, { "title": "Map Data", - "icon": "icon_navigate.png", + "icon": "navigate", "panel": "MAPS", "color": "#10B981", }, { "title": "System", - "icon": "icon_system.png", + "icon": "system", "panel": "SYSTEM", "color": "#D946EF", }, { "title": "Appearance", - "icon": "icon_display.png", + "icon": "display", "panel": "VISUALS", "color": "#8B5CF6", }, { "title": "Vehicle Settings", - "icon": "icon_vehicle.png", + "icon": "vehicle", "panel": "VEHICLE", "color": "#64748B", }, @@ -199,7 +197,7 @@ class StarPilotLayout(Widget): tile = HubTile( title=tr(cat["title"]), desc=tr(cat.get("desc", "")), - icon_path=f"{STARPILOT_ICONS_DIR}/{cat['icon']}", + icon_path=cat["icon"], on_click=on_click, starpilot_icon=True, bg_color=cat.get("color") @@ -218,7 +216,7 @@ class StarPilotLayout(Widget): tile = HubTile( title=tr(label), desc="", - icon_path=f"{STARPILOT_ICONS_DIR}/{cat['icon']}", + icon_path=cat["icon"], on_click=on_btn_click, starpilot_icon=True, bg_color=cat.get("color") diff --git a/selfdrive/ui/layouts/settings/starpilot/scribble.py b/selfdrive/ui/layouts/settings/starpilot/scribble.py new file mode 100644 index 000000000..9b1c397d4 --- /dev/null +++ b/selfdrive/ui/layouts/settings/starpilot/scribble.py @@ -0,0 +1,332 @@ +from __future__ import annotations +import math +import pyray as rl + + +def draw_custom_icon(key: str, x: float, y: float, s: float, color: rl.Color): + # Helper for drawing quadratic Bezier curves + def draw_bezier(p0: rl.Vector2, p1: rl.Vector2, p2: rl.Vector2, thick: float): + segments = 20 + for i in range(segments): + t1 = i / segments + t2 = (i + 1) / segments + x1_val = (1 - t1)**2 * p0.x + 2 * (1 - t1) * t1 * p1.x + t1**2 * p2.x + y1_val = (1 - t1)**2 * p0.y + 2 * (1 - t1) * t1 * p1.y + t1**2 * p2.y + x2_val = (1 - t2)**2 * p0.x + 2 * (1 - t2) * t2 * p1.x + t2**2 * p2.x + y2_val = (1 - t2)**2 * p0.y + 2 * (1 - t2) * t2 * p1.y + t2**2 * p2.y + rl.draw_line_ex(rl.Vector2(x1_val, y1_val), rl.Vector2(x2_val, y2_val), thick, color) + + # Helper for drawing tilted ellipse arcs + def draw_ellipse_arc(cx: float, cy: float, a: float, b: float, tilt_deg: float, start_deg: float, end_deg: float, thick: float): + tilt = math.radians(tilt_deg) + segments = 24 + step = (end_deg - start_deg) / segments + for i in range(segments): + p1 = math.radians(start_deg + i * step) + p2 = math.radians(start_deg + (i + 1) * step) + + x1_val = a * math.cos(p1) + y1_val = b * math.sin(p1) + rx1 = x1_val * math.cos(tilt) - y1_val * math.sin(tilt) + ry1 = x1_val * math.sin(tilt) + y1_val * math.cos(tilt) + + x2_val = a * math.cos(p2) + y2_val = b * math.sin(p2) + rx2 = x2_val * math.cos(tilt) - y2_val * math.sin(tilt) + ry2 = x2_val * math.sin(tilt) + y2_val * math.cos(tilt) + + rl.draw_line_ex(rl.Vector2(cx + rx1, cy + ry1), rl.Vector2(cx + rx2, cy + ry2), thick, color) + + # Helper for drawing 4-pointed stars + def draw_star(cx: float, cy: float, R: float, r: float): + v1a = rl.Vector2(cx - r, cy - r) + v1b = rl.Vector2(cx + r, cy - r) + v1c = rl.Vector2(cx, cy - R) + + v2a = rl.Vector2(cx + r, cy - r) + v2b = rl.Vector2(cx + r, cy + r) + v2c = rl.Vector2(cx + R, cy) + + v3a = rl.Vector2(cx + r, cy + r) + v3b = rl.Vector2(cx - r, cy + r) + v3c = rl.Vector2(cx, cy + R) + + v4a = rl.Vector2(cx - r, cy + r) + v4b = rl.Vector2(cx - r, cy - r) + v4c = rl.Vector2(cx - R, cy) + + rl.draw_triangle(v1a, v1b, v1c, color) + rl.draw_triangle(v2a, v2b, v2c, color) + rl.draw_triangle(v3a, v3b, v3c, color) + rl.draw_triangle(v4a, v4b, v4c, color) + rl.draw_circle_v(rl.Vector2(cx, cy), r, color) + + if key == "sound": + # Alerts & Sounds: Bell with side arcs + x_c = x + 30.0 * s + y_dome = y + 28.0 * s + + # Side arcs representing sound waves (left and right) + draw_ellipse_arc(x_c, y_dome, 18.0 * s, 9.0 * s, -15.0, 135.0, 225.0, 2.0 * s) + draw_ellipse_arc(x_c, y_dome, 26.0 * s, 13.0 * s, -15.0, 135.0, 225.0, 2.0 * s) + draw_ellipse_arc(x_c, y_dome, 18.0 * s, 9.0 * s, -15.0, -45.0, 45.0, 2.0 * s) + draw_ellipse_arc(x_c, y_dome, 26.0 * s, 13.0 * s, -15.0, -45.0, 45.0, 2.0 * s) + + # Top loop (handle) + rl.draw_ring(rl.Vector2(x_c, y_dome - 9.5 * s), 1.5 * s, 3.5 * s, 180.0, 360.0, 16, color) + + # Bell dome + rl.draw_circle_sector(rl.Vector2(x_c, y_dome), 9.5 * s, 180.0, 360.0, 24, color) + + # Main bell body + rl.draw_rectangle_rec(rl.Rectangle(x_c - 9.5 * s, y_dome, 19.0 * s, 9.0 * s), color) + + # Flared skirt + rl.draw_rectangle_rec(rl.Rectangle(x_c - 9.5 * s, y_dome + 9.0 * s, 19.0 * s, 4.0 * s), color) + rl.draw_triangle( + rl.Vector2(x_c - 9.5 * s, y_dome + 9.0 * s), + rl.Vector2(x_c - 13.5 * s, y_dome + 13.0 * s), + rl.Vector2(x_c - 9.5 * s, y_dome + 13.0 * s), + color + ) + rl.draw_triangle( + rl.Vector2(x_c + 9.5 * s, y_dome + 9.0 * s), + rl.Vector2(x_c + 9.5 * s, y_dome + 13.0 * s), + rl.Vector2(x_c + 13.5 * s, y_dome + 13.0 * s), + color + ) + + # Bottom lip + rl.draw_rectangle_rounded(rl.Rectangle(x_c - 14.5 * s, y_dome + 13.0 * s, 29.0 * s, 3.0 * s), 1.0, 4, color) + + # Clapper + rl.draw_circle_v(rl.Vector2(x_c, y_dome + 18.0 * s), 3.5 * s, color) + + elif key == "steering": + # Driving Controls: Steering wheel with center hub + x_c = x + 30.0 * s + y_c = y + 30.0 * s + center = rl.Vector2(x_c, y_c) + + # Outer rim + rl.draw_ring(center, 19.5 * s, 22.0 * s, 0.0, 360.0, 48, color) + + # Thumb rests + rl.draw_circle_v(rl.Vector2(x_c - 17.5 * s, y_c - 8.0 * s), 2.5 * s, color) + rl.draw_circle_v(rl.Vector2(x_c + 17.5 * s, y_c - 8.0 * s), 2.5 * s, color) + + # Inner ring in hub + rl.draw_ring(center, 4.5 * s, 5.5 * s, 0.0, 360.0, 24, color) + + # Center star + draw_star(x_c, y_c, 4.5 * s, 1.5 * s) + + # Three spokes + rl.draw_line_ex(rl.Vector2(x_c - 5.5 * s, y_c + 1.0 * s), rl.Vector2(x_c - 19.5 * s, y_c + 4.0 * s), 2.5 * s, color) + rl.draw_line_ex(rl.Vector2(x_c + 5.5 * s, y_c + 1.0 * s), rl.Vector2(x_c + 19.5 * s, y_c + 4.0 * s), 2.5 * s, color) + rl.draw_line_ex(rl.Vector2(x_c, y_c + 5.5 * s), rl.Vector2(x_c, y_c + 19.5 * s), 2.5 * s, color) + + elif key == "navigate": + # Map Data: Path with starting indicator and destination crosshair + x_s = x + 12.0 * s + y_s = y + 48.0 * s + x_d = x + 48.0 * s + y_d = y + 14.0 * s + + # Start node + rl.draw_circle_v(rl.Vector2(x_s, y_s), 3.0 * s, color) + rl.draw_line_ex(rl.Vector2(x_s, y_s - 3.0 * s), rl.Vector2(x_s, y_s - 6.0 * s), 1.5 * s, color) + rl.draw_line_ex(rl.Vector2(x_s, y_s + 3.0 * s), rl.Vector2(x_s, y_s + 6.0 * s), 1.5 * s, color) + rl.draw_line_ex(rl.Vector2(x_s - 3.0 * s, y_s), rl.Vector2(x_s - 6.0 * s, y_s), 1.5 * s, color) + rl.draw_line_ex(rl.Vector2(x_s + 3.0 * s, y_s), rl.Vector2(x_s + 6.0 * s, y_s), 1.5 * s, color) + + # Sweeping curved path + p0 = rl.Vector2(x_s, y_s) + p1 = rl.Vector2(x + 40.0 * s, y + 42.0 * s) + p2 = rl.Vector2(x_d, y_d) + draw_bezier(p0, p1, p2, 3.0 * s) + + # Destination crosshair + rl.draw_ring(rl.Vector2(x_d, y_d), 5.5 * s, 6.5 * s, 0.0, 360.0, 24, color) + rl.draw_line_ex(rl.Vector2(x_d, y_d - 9.0 * s), rl.Vector2(x_d, y_d - 5.5 * s), 1.5 * s, color) + rl.draw_line_ex(rl.Vector2(x_d, y_d + 5.5 * s), rl.Vector2(x_d, y_d + 9.0 * s), 1.5 * s, color) + rl.draw_line_ex(rl.Vector2(x_d - 9.0 * s, y_d), rl.Vector2(x_d - 5.5 * s, y_d), 1.5 * s, color) + rl.draw_line_ex(rl.Vector2(x_d + 5.5 * s, y_d), rl.Vector2(x_d + 9.0 * s, y_d), 1.5 * s, color) + + # Center star + draw_star(x_d, y_d, 4.0 * s, 1.25 * s) + + elif key == "system": + # System Settings: Interlocking gears + cx1, cy1 = x + 23.0 * s, y + 23.0 * s + cx2, cy2 = x + 41.0 * s, y + 41.0 * s + + # Gear 1 (Large) + # Ring body + rl.draw_ring(rl.Vector2(cx1, cy1), 6.0 * s, 12.0 * s, 0.0, 360.0, 36, color) + # Center star (spokes/core) + draw_star(cx1, cy1, 6.0 * s, 2.0 * s) + # Teeth (8 cogs, blocky teeth meshing cleanly) + for i in range(8): + angle_rad = math.radians(i * 45.0) + cos_a = math.cos(angle_rad) + sin_a = math.sin(angle_rad) + rl.draw_line_ex( + rl.Vector2(cx1 + cos_a * 11.5 * s, cy1 + sin_a * 11.5 * s), + rl.Vector2(cx1 + cos_a * 15.5 * s, cy1 + sin_a * 15.5 * s), + 5.0 * s, + color + ) + + # Gear 2 (Small) + # Ring body + rl.draw_ring(rl.Vector2(cx2, cy2), 4.5 * s, 9.0 * s, 0.0, 360.0, 24, color) + # Center star (spokes/core) + draw_star(cx2, cy2, 4.5 * s, 1.5 * s) + # Teeth (6 cogs, offset by 15 degrees to mesh perfectly) + for j in range(6): + angle_rad = math.radians(15.0 + j * 60.0) + cos_a = math.cos(angle_rad) + sin_a = math.sin(angle_rad) + rl.draw_line_ex( + rl.Vector2(cx2 + cos_a * 8.5 * s, cy2 + sin_a * 8.5 * s), + rl.Vector2(cx2 + cos_a * 12.0 * s, cy2 + sin_a * 12.0 * s), + 4.0 * s, + color + ) + + elif key == "display": + # Outer screen bezel - Chamfered modern rectangular shape + p1 = rl.Vector2(x + 9.0 * s, y + 11.0 * s) + p2 = rl.Vector2(x + 51.0 * s, y + 11.0 * s) + p3 = rl.Vector2(x + 54.0 * s, y + 14.0 * s) + p4 = rl.Vector2(x + 54.0 * s, y + 36.0 * s) + p5 = rl.Vector2(x + 51.0 * s, y + 39.0 * s) + p6 = rl.Vector2(x + 9.0 * s, y + 39.0 * s) + p7 = rl.Vector2(x + 6.0 * s, y + 36.0 * s) + p8 = rl.Vector2(x + 6.0 * s, y + 14.0 * s) + + rl.draw_line_ex(p1, p2, 2.0 * s, color) + rl.draw_line_ex(p2, p3, 2.0 * s, color) + rl.draw_line_ex(p3, p4, 2.0 * s, color) + rl.draw_line_ex(p4, p5, 2.0 * s, color) + rl.draw_line_ex(p5, p6, 2.0 * s, color) + rl.draw_line_ex(p6, p7, 2.0 * s, color) + rl.draw_line_ex(p7, p8, 2.0 * s, color) + rl.draw_line_ex(p8, p1, 2.0 * s, color) + + # Inner bezel - Offset chamfered line to establish depth + ip1 = rl.Vector2(x + 10.5 * s, y + 13.0 * s) + ip2 = rl.Vector2(x + 49.5 * s, y + 13.0 * s) + ip3 = rl.Vector2(x + 52.0 * s, y + 15.5 * s) + ip4 = rl.Vector2(x + 52.0 * s, y + 34.5 * s) + ip5 = rl.Vector2(x + 49.5 * s, y + 37.0 * s) + ip6 = rl.Vector2(x + 10.5 * s, y + 37.0 * s) + ip7 = rl.Vector2(x + 8.0 * s, y + 34.5 * s) + ip8 = rl.Vector2(x + 8.0 * s, y + 15.5 * s) + + rl.draw_line_ex(ip1, ip2, 1.0 * s, color) + rl.draw_line_ex(ip2, ip3, 1.0 * s, color) + rl.draw_line_ex(ip3, ip4, 1.0 * s, color) + rl.draw_line_ex(ip4, ip5, 1.0 * s, color) + rl.draw_line_ex(ip5, ip6, 1.0 * s, color) + rl.draw_line_ex(ip6, ip7, 1.0 * s, color) + rl.draw_line_ex(ip7, ip8, 1.0 * s, color) + rl.draw_line_ex(ip8, ip1, 1.0 * s, color) + + # Dash Bracket Mount (Porsche engineered stability) + rl.draw_line_ex(rl.Vector2(x + 12.0 * s, y + 53.0 * s), rl.Vector2(x + 48.0 * s, y + 53.0 * s), 2.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 22.0 * s, y + 39.0 * s), rl.Vector2(x + 18.0 * s, y + 53.0 * s), 2.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 38.0 * s, y + 39.0 * s), rl.Vector2(x + 42.0 * s, y + 53.0 * s), 2.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 20.0 * s, y + 46.0 * s), rl.Vector2(x + 40.0 * s, y + 46.0 * s), 1.5 * s, color) + rl.draw_circle_v(rl.Vector2(x + 30.0 * s, y + 49.0 * s), 2.5 * s, color) + + # Flight Path Vector (FPV) + rl.draw_ring(rl.Vector2(x + 30.0 * s, y + 25.0 * s), 0.75 * s, 1.75 * s, 0.0, 360.0, 16, color) + rl.draw_line_ex(rl.Vector2(x + 25.0 * s, y + 25.0 * s), rl.Vector2(x + 28.0 * s, y + 25.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 32.0 * s, y + 25.0 * s), rl.Vector2(x + 35.0 * s, y + 25.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 30.0 * s, y + 21.0 * s), rl.Vector2(x + 30.0 * s, y + 23.0 * s), 1.0 * s, color) + + # Attitude Horizon Lines + rl.draw_line_ex(rl.Vector2(x + 14.0 * s, y + 25.0 * s), rl.Vector2(x + 22.0 * s, y + 25.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 38.0 * s, y + 25.0 * s), rl.Vector2(x + 46.0 * s, y + 25.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 14.0 * s, y + 25.0 * s), rl.Vector2(x + 14.0 * s, y + 22.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 22.0 * s, y + 25.0 * s), rl.Vector2(x + 22.0 * s, y + 28.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 38.0 * s, y + 25.0 * s), rl.Vector2(x + 38.0 * s, y + 28.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 46.0 * s, y + 25.0 * s), rl.Vector2(x + 46.0 * s, y + 22.0 * s), 1.0 * s, color) + + # Pitch Ladder (above/below horizon) + rl.draw_line_ex(rl.Vector2(x + 25.0 * s, y + 19.0 * s), rl.Vector2(x + 27.5 * s, y + 19.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 32.5 * s, y + 19.0 * s), rl.Vector2(x + 35.0 * s, y + 19.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 25.0 * s, y + 19.0 * s), rl.Vector2(x + 25.0 * s, y + 20.5 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 35.0 * s, y + 19.0 * s), rl.Vector2(x + 35.0 * s, y + 20.5 * s), 1.0 * s, color) + + rl.draw_line_ex(rl.Vector2(x + 25.0 * s, y + 31.0 * s), rl.Vector2(x + 27.5 * s, y + 31.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 32.5 * s, y + 31.0 * s), rl.Vector2(x + 35.0 * s, y + 31.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 25.0 * s, y + 31.0 * s), rl.Vector2(x + 25.0 * s, y + 29.5 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 35.0 * s, y + 31.0 * s), rl.Vector2(x + 35.0 * s, y + 29.5 * s), 1.0 * s, color) + + # Telemetry HUD Tapes (Speed and Altitude) + rl.draw_line_ex(rl.Vector2(x + 11.0 * s, y + 16.0 * s), rl.Vector2(x + 11.0 * s, y + 34.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 11.0 * s, y + 18.0 * s), rl.Vector2(x + 13.0 * s, y + 18.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 11.0 * s, y + 22.0 * s), rl.Vector2(x + 14.5 * s, y + 22.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 11.0 * s, y + 26.0 * s), rl.Vector2(x + 13.0 * s, y + 26.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 11.0 * s, y + 30.0 * s), rl.Vector2(x + 14.5 * s, y + 30.0 * s), 1.0 * s, color) + + rl.draw_line_ex(rl.Vector2(x + 49.0 * s, y + 16.0 * s), rl.Vector2(x + 49.0 * s, y + 34.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 47.0 * s, y + 18.0 * s), rl.Vector2(x + 49.0 * s, y + 18.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 45.5 * s, y + 22.0 * s), rl.Vector2(x + 49.0 * s, y + 22.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 47.0 * s, y + 26.0 * s), rl.Vector2(x + 49.0 * s, y + 26.0 * s), 1.0 * s, color) + rl.draw_line_ex(rl.Vector2(x + 45.5 * s, y + 30.0 * s), rl.Vector2(x + 49.0 * s, y + 30.0 * s), 1.0 * s, color) + + # Curved Horizon / Orbital sweep (Mercedes curves) + p0_curve = rl.Vector2(x + 15.0 * s, y + 34.0 * s) + p1_curve = rl.Vector2(x + 30.0 * s, y + 29.0 * s) + p2_curve = rl.Vector2(x + 45.0 * s, y + 34.0 * s) + draw_bezier(p0_curve, p1_curve, p2_curve, 1.0 * s) + + # Celestial Galaxy-themed accents (Space Vista) + draw_star(x + 15.0 * s, y + 17.0 * s, 1.5 * s, 0.5 * s) + rl.draw_ring(rl.Vector2(x + 44.0 * s, y + 17.0 * s), 1.5 * s, 2.5 * s, 220.0, 320.0, 12, color) + draw_star(x + 42.0 * s, y + 15.0 * s, 1.25 * s, 0.4 * s) + + elif key == "vehicle": + # Vehicle Settings: Aerodynamic car silhouette floating over curved base + # Curved base line + rl.draw_ring(rl.Vector2(x + 30.0 * s, y + 110.0 * s), 64.0 * s, 66.5 * s, 245.0, 295.0, 36, color) + + # Vehicle silhouette + v_front = rl.Vector2(x + 10.0 * s, y + 31.0 * s) + v_hood_end = rl.Vector2(x + 20.0 * s, y + 25.0 * s) + v_cabin_end = rl.Vector2(x + 38.0 * s, y + 19.0 * s) + v_rear = rl.Vector2(x + 50.0 * s, y + 31.0 * s) + + # Front bumper and hood + rl.draw_line_ex(rl.Vector2(x + 10.0 * s, y + 31.0 * s), rl.Vector2(x + 10.0 * s, y + 34.0 * s), 2.0 * s, color) + draw_bezier(v_front, rl.Vector2(x + 13.0 * s, y + 28.0 * s), v_hood_end, 2.0 * s) + + # Cabin roofline + draw_bezier(v_hood_end, rl.Vector2(x + 27.0 * s, y + 19.0 * s), v_cabin_end, 2.0 * s) + + # Rear glass and tail + draw_bezier(v_cabin_end, rl.Vector2(x + 46.0 * s, y + 21.0 * s), v_rear, 2.0 * s) + rl.draw_line_ex(v_rear, rl.Vector2(x + 50.0 * s, y + 34.0 * s), 2.0 * s, color) + + # Underbody and wheel arches + rl.draw_line_ex(rl.Vector2(x + 10.0 * s, y + 34.0 * s), rl.Vector2(x + 14.5 * s, y + 34.0 * s), 2.0 * s, color) + rl.draw_ring(rl.Vector2(x + 19.0 * s, y + 34.0 * s), 4.5 * s, 5.5 * s, 180.0, 360.0, 12, color) + rl.draw_line_ex(rl.Vector2(x + 23.5 * s, y + 34.0 * s), rl.Vector2(x + 37.5 * s, y + 34.0 * s), 2.0 * s, color) + rl.draw_ring(rl.Vector2(x + 42.0 * s, y + 34.0 * s), 4.5 * s, 5.5 * s, 180.0, 360.0, 12, color) + rl.draw_line_ex(rl.Vector2(x + 46.5 * s, y + 34.0 * s), rl.Vector2(x + 50.0 * s, y + 34.0 * s), 2.0 * s, color) + + # Wheels + rl.draw_ring(rl.Vector2(x + 19.0 * s, y + 34.0 * s), 2.5 * s, 4.0 * s, 0.0, 360.0, 16, color) + rl.draw_ring(rl.Vector2(x + 42.0 * s, y + 34.0 * s), 2.5 * s, 4.0 * s, 0.0, 360.0, 16, color) + + # Cabin window + rl.draw_line_ex(rl.Vector2(x + 22.0 * s, y + 25.0 * s), rl.Vector2(x + 37.0 * s, y + 21.0 * s), 1.5 * s, color) + rl.draw_line_ex(rl.Vector2(x + 37.0 * s, y + 21.0 * s), rl.Vector2(x + 38.0 * s, y + 25.0 * s), 1.5 * s, color) + rl.draw_line_ex(rl.Vector2(x + 38.0 * s, y + 25.0 * s), rl.Vector2(x + 22.0 * s, y + 25.0 * s), 1.5 * s, color) + + # Background star accent + draw_star(x + 14.0 * s, y + 12.0 * s, 3.0 * s, 1.0 * s)