feat(patterns): merge pattern styles and add mode support
Consolidate legacy pattern ids into meteor, particles, sparkle, chase, and colour_cycle with n6/mode style selection; add pattern_modes helper, self-contained tests/all.py, and preset mode alias on wire. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
108
src/patterns/particles.py
Normal file
108
src/patterns/particles.py
Normal file
@@ -0,0 +1,108 @@
|
||||
import random
|
||||
import utime
|
||||
|
||||
from patterns.pattern_modes import style_mode
|
||||
|
||||
_LEGACY = {"starfall": 1}
|
||||
|
||||
|
||||
class Particles:
|
||||
def __init__(self, driver):
|
||||
self.driver = driver
|
||||
|
||||
def _run_snowfall(self, preset, colors, flakes, last):
|
||||
density = max(1, int(preset.n1) if int(preset.n1) > 0 else 20)
|
||||
speed = max(1, int(preset.n2) if int(preset.n2) > 0 else 1)
|
||||
d = max(1, int(preset.d))
|
||||
now = utime.ticks_ms()
|
||||
if utime.ticks_diff(now, last) < d:
|
||||
return flakes, last, False
|
||||
bg_color = self.driver.apply_brightness(preset.background_or(colors), preset.b)
|
||||
if random.randint(0, 255) < density:
|
||||
flakes.append([self.driver.num_leds - 1, random.randint(0, len(colors) - 1)])
|
||||
for i in range(self.driver.num_leds):
|
||||
self.driver.n[i] = bg_color
|
||||
nf = []
|
||||
for pos, ci in flakes:
|
||||
if 0 <= pos < self.driver.num_leds:
|
||||
self.driver.n[pos] = self.driver.apply_brightness(colors[ci], preset.b)
|
||||
pos -= speed
|
||||
if pos >= -1:
|
||||
nf.append([pos, ci])
|
||||
self.driver.n.write()
|
||||
return nf, utime.ticks_add(last, d), True
|
||||
|
||||
def _run_starfall(self, preset, colors, stars, last):
|
||||
rate = max(1, min(255, int(preset.n1) if int(preset.n1) > 0 else 14))
|
||||
speed = max(1, int(preset.n2) if int(preset.n2) > 0 else 2)
|
||||
tail = max(2, int(preset.n3) if int(preset.n3) > 0 else 10)
|
||||
max_stars = 4
|
||||
d = max(1, int(preset.d))
|
||||
now = utime.ticks_ms()
|
||||
if utime.ticks_diff(now, last) < d:
|
||||
return stars, last, False
|
||||
bg = self.driver.apply_brightness(preset.background_or(colors), preset.b)
|
||||
for i in range(self.driver.num_leds):
|
||||
self.driver.n[i] = bg
|
||||
if len(stars) < max_stars and random.randint(0, 255) < rate:
|
||||
top = self.driver.num_leds - 1 + random.randint(
|
||||
0, min(8, self.driver.num_leds // 2)
|
||||
)
|
||||
stars.append({"h": float(top), "ci": random.randint(0, len(colors) - 1)})
|
||||
ns = []
|
||||
for s in stars:
|
||||
h = s["h"]
|
||||
ci = s["ci"]
|
||||
ih = int(h)
|
||||
for t in range(tail):
|
||||
idx = ih + t
|
||||
if 0 <= idx < self.driver.num_leds:
|
||||
fade = 255 - (t * 255 // max(1, tail - 1))
|
||||
base = colors[ci]
|
||||
lit = (
|
||||
(base[0] * fade) // 255,
|
||||
(base[1] * fade) // 255,
|
||||
(base[2] * fade) // 255,
|
||||
)
|
||||
lit = self.driver.apply_brightness(lit, preset.b)
|
||||
o = self.driver.n[idx]
|
||||
self.driver.n[idx] = (
|
||||
max(o[0], lit[0]),
|
||||
max(o[1], lit[1]),
|
||||
max(o[2], lit[2]),
|
||||
)
|
||||
h -= speed
|
||||
if h >= -tail:
|
||||
s["h"] = h
|
||||
ns.append(s)
|
||||
stars = ns
|
||||
self.driver.n.write()
|
||||
return stars, utime.ticks_add(last, d), True
|
||||
|
||||
def run(self, preset):
|
||||
"""Falling particles: n6 0 snowfall flakes, 1 starfall streaks."""
|
||||
mode = style_mode(preset, 0, _LEGACY)
|
||||
colors = preset.c if preset.c else [(255, 255, 255), (180, 220, 255)]
|
||||
last = utime.ticks_ms()
|
||||
|
||||
if mode == 1:
|
||||
colors = preset.c if preset.c else [
|
||||
(255, 255, 255),
|
||||
(200, 230, 255),
|
||||
(255, 248, 220),
|
||||
]
|
||||
stars = []
|
||||
while True:
|
||||
stars, last, stepped = self._run_starfall(preset, colors, stars, last)
|
||||
if stepped and not preset.a:
|
||||
yield
|
||||
return
|
||||
yield
|
||||
|
||||
flakes = []
|
||||
while True:
|
||||
flakes, last, stepped = self._run_snowfall(preset, colors, flakes, last)
|
||||
if stepped and not preset.a:
|
||||
yield
|
||||
return
|
||||
yield
|
||||
Reference in New Issue
Block a user