54e6124925
version: sunnypilot v2026.001.000 (dev) date: 2026-05-07T23:07:19 master commit: c28eb958740187620f2282023b8f1997cf90f583
80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
"""
|
|
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
|
|
|
This file is part of sunnypilot and is licensed under the MIT License.
|
|
See the LICENSE.md file in the root directory for more details.
|
|
"""
|
|
import time
|
|
import colorsys
|
|
import pyray as rl
|
|
from openpilot.system.ui.lib.shader_polygon import draw_polygon, Gradient
|
|
|
|
|
|
class RainbowPath:
|
|
DEFAULT_NUM_SEGMENTS = 8
|
|
DEFAULT_SPEED = 50.0 # degrees per second
|
|
DEFAULT_SATURATION = 0.9
|
|
DEFAULT_LIGHTNESS = 0.6
|
|
BASE_ALPHA = 0.8
|
|
ALPHA_FADE = 0.3 # Alpha reduction from bottom to top
|
|
|
|
def __init__(self, num_segments: int = DEFAULT_NUM_SEGMENTS, speed: float = DEFAULT_SPEED,
|
|
saturation: float = DEFAULT_SATURATION, lightness: float = DEFAULT_LIGHTNESS):
|
|
self.num_segments = num_segments
|
|
self.speed = speed
|
|
self.saturation = saturation
|
|
self.lightness = lightness
|
|
|
|
def set_speed(self, speed: float):
|
|
self.speed = speed
|
|
|
|
def set_num_segments(self, num_segments: int):
|
|
self.num_segments = num_segments
|
|
|
|
def set_saturation(self, saturation: float):
|
|
self.saturation = max(0.0, min(1.0, saturation))
|
|
|
|
def set_lightness(self, lightness: float):
|
|
self.lightness = max(0.0, min(1.0, lightness))
|
|
|
|
def get_gradient(self) -> Gradient:
|
|
time_offset = time.monotonic()
|
|
hue_offset = (time_offset * self.speed) % 360.0
|
|
|
|
segment_colors = []
|
|
gradient_stops = []
|
|
|
|
for i in range(self.num_segments):
|
|
position = i / (self.num_segments - 1)
|
|
hue = (hue_offset + position * 360.0) % 360.0
|
|
alpha = self.BASE_ALPHA * (1.0 - position * self.ALPHA_FADE)
|
|
color = self._hsla_to_color(
|
|
hue / 360.0,
|
|
self.saturation,
|
|
self.lightness,
|
|
alpha
|
|
)
|
|
gradient_stops.append(position)
|
|
segment_colors.append(color)
|
|
|
|
return Gradient(
|
|
start=(0.0, 1.0), # Bottom of path
|
|
end=(0.0, 0.0), # Top of path
|
|
colors=segment_colors,
|
|
stops=gradient_stops,
|
|
)
|
|
|
|
@staticmethod
|
|
def _hsla_to_color(h: float, s: float, l: float, a: float) -> rl.Color:
|
|
rgb = colorsys.hls_to_rgb(h, l, s)
|
|
return rl.Color(
|
|
int(rgb[0] * 255),
|
|
int(rgb[1] * 255),
|
|
int(rgb[2] * 255),
|
|
int(a * 255)
|
|
)
|
|
|
|
def draw_rainbow_path(self, rect, path):
|
|
gradient = self.get_gradient()
|
|
draw_polygon(rect, path.projected_points, gradient=gradient)
|