tuanchris 3 mesi fa
parent
commit
28f75eecc6
1 ha cambiato i file con 388 aggiunte e 0 eliminazioni
  1. 388 0
      modules/led/dw_leds/effects/basic_effects.py

+ 388 - 0
modules/led/dw_leds/effects/basic_effects.py

@@ -302,6 +302,379 @@ def mode_sparkle(seg: Segment) -> int:
     seg.set_pixel_color(seg.aux0, seg.get_color(0))
     return FRAMETIME
 
+def mode_fire(seg: Segment) -> int:
+    """Fire/flame effect"""
+    if seg.call == 0:
+        seg.data = [0] * seg.length
+
+    # Cooling parameter (higher = cooler flames)
+    cooling = ((100 - (seg.intensity >> 1)) * 10) // seg.length + 2
+
+    # Heat decay for all pixels
+    for i in range(seg.length):
+        cool_down = random.randint(0, cooling)
+        seg.data[i] = max(0, seg.data[i] - cool_down)
+
+    # Heat drift upward
+    for i in range(seg.length - 1, 2, -1):
+        seg.data[i] = (seg.data[i - 1] + seg.data[i - 2] + seg.data[i - 2]) // 3
+
+    # Randomly ignite new sparks near bottom
+    if random.randint(0, 255) < seg.intensity:
+        spark_pos = random.randint(0, min(7, seg.length - 1))
+        seg.data[spark_pos] = min(255, seg.data[spark_pos] + random.randint(160, 255))
+
+    # Convert heat to colors
+    for i in range(seg.length):
+        heat = seg.data[i]
+
+        # Black -> Red -> Yellow -> White
+        if heat < 85:
+            color = (heat * 3, 0, 0)
+        elif heat < 170:
+            h = heat - 85
+            color = (255, h * 3, 0)
+        else:
+            h = heat - 170
+            color = (255, 255, h * 3)
+
+        r, g, b = color
+        seg.set_pixel_color(i, (r << 16) | (g << 8) | b)
+
+    return FRAMETIME
+
+def mode_comet(seg: Segment) -> int:
+    """Comet/shooting star effect"""
+    if seg.call == 0:
+        seg.aux0 = 0
+        seg.aux1 = 0
+
+    seg.fade_out(128)
+
+    size = 1 + ((seg.intensity * seg.length) >> 9)
+    cycle_time = 10 + (255 - seg.speed)
+    iteration = seg.now() // cycle_time
+
+    if iteration != seg.step:
+        seg.aux0 = (seg.aux0 + 1) % seg.length
+        seg.step = iteration
+
+    # Draw comet
+    for i in range(size):
+        pos = (seg.aux0 - i) % seg.length
+        brightness = 255 - (i * 255 // max(1, size))
+        color = color_blend(0, seg.color_from_palette(pos), brightness)
+        seg.set_pixel_color(pos, color)
+
+    return FRAMETIME
+
+def mode_chase(seg: Segment) -> int:
+    """Chase effect with colored segments"""
+    if seg.call == 0:
+        seg.aux0 = 0
+
+    size = max(1, seg.length // 4)
+    cycle_time = 10 + (255 - seg.speed)
+    iteration = seg.now() // cycle_time
+
+    if iteration != seg.step:
+        seg.aux0 = (seg.aux0 + 1) % seg.length
+        seg.step = iteration
+
+    seg.fill(seg.get_color(1))
+
+    for i in range(size):
+        pos = (seg.aux0 + i) % seg.length
+        seg.set_pixel_color(pos, seg.color_from_palette(pos))
+
+    return FRAMETIME
+
+def mode_police(seg: Segment) -> int:
+    """Police lights (red/blue alternating)"""
+    cycle_time = 25 + (255 - seg.speed)
+    on_time = cycle_time // 2
+
+    now = seg.now()
+    iteration = now // cycle_time
+    rem = now % cycle_time
+    on = rem < on_time
+
+    half = seg.length // 2
+
+    # Red on left, blue on right
+    red = (255, 0, 0)
+    blue = (0, 0, 255)
+    off_color = (0, 0, 0)
+
+    for i in range(half):
+        if (iteration % 2 == 0 and on) or (iteration % 2 == 1 and not on):
+            seg.set_pixel_color(i, (red[0] << 16) | (red[1] << 8) | red[2])
+        else:
+            seg.set_pixel_color(i, (off_color[0] << 16) | (off_color[1] << 8) | off_color[2])
+
+    for i in range(half, seg.length):
+        if (iteration % 2 == 1 and on) or (iteration % 2 == 0 and not on):
+            seg.set_pixel_color(i, (blue[0] << 16) | (blue[1] << 8) | blue[2])
+        else:
+            seg.set_pixel_color(i, (off_color[0] << 16) | (off_color[1] << 8) | off_color[2])
+
+    return FRAMETIME
+
+def mode_lightning(seg: Segment) -> int:
+    """Lightning flash effect"""
+    if seg.call == 0:
+        seg.aux0 = 0
+        seg.aux1 = 0
+
+    cycle_time = 50 + (255 - seg.speed) * 10
+    iteration = seg.now() // cycle_time
+
+    if iteration != seg.step:
+        # Random chance of lightning
+        if random.randint(0, 255) < seg.intensity:
+            seg.aux0 = random.randint(3, 8)  # Number of flashes
+            seg.aux1 = seg.now()
+        seg.step = iteration
+
+    # Flash sequence
+    if seg.aux0 > 0:
+        flash_duration = 50
+        time_since = seg.now() - seg.aux1
+
+        if time_since < flash_duration:
+            # Flash on
+            brightness = 255 - (time_since * 255 // flash_duration)
+            for i in range(seg.length):
+                color = color_blend(0, WHITE, brightness)
+                seg.set_pixel_color(i, color)
+        else:
+            # Flash off, wait for next
+            if time_since > flash_duration + random.randint(10, 100):
+                seg.aux0 -= 1
+                seg.aux1 = seg.now()
+            else:
+                seg.fill(seg.get_color(1))
+    else:
+        seg.fill(seg.get_color(1))
+
+    return FRAMETIME
+
+def mode_fireworks(seg: Segment) -> int:
+    """Fireworks effect"""
+    seg.fade_out(64)
+
+    cycle_time = 20 + (255 - seg.speed)
+    iteration = seg.now() // cycle_time
+
+    if iteration != seg.step:
+        # Launch new firework
+        if random.randint(0, 255) < seg.intensity:
+            pos = random.randint(0, seg.length - 1)
+            color = color_wheel(random.randint(0, 255))
+
+            # Bright center
+            seg.set_pixel_color(pos, color)
+
+            # Dimmer neighbors
+            if pos > 0:
+                seg.set_pixel_color(pos - 1, color_blend(0, color, 128))
+            if pos < seg.length - 1:
+                seg.set_pixel_color(pos + 1, color_blend(0, color, 128))
+
+        seg.step = iteration
+
+    return FRAMETIME
+
+def mode_ripple(seg: Segment) -> int:
+    """Ripple effect"""
+    if seg.call == 0:
+        seg.data = [0] * seg.length
+        seg.aux0 = seg.length // 2
+
+    seg.fade_out(250)
+
+    cycle_time = 50 + (255 - seg.speed) * 2
+    iteration = seg.now() // cycle_time
+
+    if iteration != seg.step:
+        # New ripple
+        if random.randint(0, 255) < seg.intensity:
+            seg.aux0 = random.randint(0, seg.length - 1)
+            seg.data[seg.aux0] = 255
+
+        # Propagate ripple
+        new_data = seg.data.copy()
+        for i in range(1, seg.length - 1):
+            new_data[i] = (seg.data[i - 1] + seg.data[i + 1]) // 2
+        seg.data = new_data
+
+        seg.step = iteration
+
+    for i in range(seg.length):
+        if seg.data[i] > 0:
+            color = color_blend(seg.get_color(1),
+                              seg.color_from_palette(i),
+                              seg.data[i])
+            seg.set_pixel_color(i, color)
+
+    return FRAMETIME
+
+def mode_flow(seg: Segment) -> int:
+    """Smooth flowing color movement"""
+    counter = seg.now() * ((seg.speed >> 3) + 1)
+
+    for i in range(seg.length):
+        pos = ((i * 256 // seg.length) + counter) & 0xFFFF
+        color = color_wheel((pos >> 8) & 0xFF)
+
+        # Apply intensity as brightness modulation
+        brightness = 128 + ((sin8((pos >> 7) & 0xFF) - 128) * seg.intensity // 255)
+        color = color_blend(0, color, brightness)
+        seg.set_pixel_color(i, color)
+
+    return FRAMETIME
+
+def mode_colorloop(seg: Segment) -> int:
+    """Smooth color loop across entire strip"""
+    counter = (seg.now() * ((seg.speed >> 3) + 1)) & 0xFFFF
+
+    for i in range(seg.length):
+        # Create gradient based on position and time
+        hue = ((i * 256 // max(1, seg.length)) + (counter >> 7)) & 0xFF
+        color = color_wheel(hue)
+
+        # Intensity controls saturation
+        if seg.intensity < 255:
+            color = color_blend(color, WHITE, 255 - seg.intensity)
+
+        seg.set_pixel_color(i, color)
+
+    return FRAMETIME
+
+def mode_palette_flow(seg: Segment) -> int:
+    """Flowing palette colors"""
+    counter = seg.now() * ((seg.speed >> 3) + 1)
+
+    for i in range(seg.length):
+        # Get color from palette based on position and time
+        palette_pos = ((i * 255 // max(1, seg.length)) + (counter >> 7)) & 0xFF
+        color = seg.color_from_palette(palette_pos)
+
+        # Intensity controls brightness modulation
+        if seg.intensity < 255:
+            brightness = 128 + ((sin8(palette_pos) - 128) * seg.intensity // 255)
+            color = color_blend(0, color, brightness)
+
+        seg.set_pixel_color(i, color)
+
+    return FRAMETIME
+
+def mode_gradient(seg: Segment) -> int:
+    """Smooth gradient between colors"""
+    for i in range(seg.length):
+        # Create gradient from color 0 to color 2
+        blend_amount = (i * 255) // max(1, seg.length - 1)
+        color = color_blend(seg.get_color(0), seg.get_color(2), blend_amount)
+
+        # Intensity controls a pulsing brightness
+        if seg.intensity > 0:
+            counter = (seg.now() * ((seg.speed >> 3) + 1)) & 0xFFFF
+            pulse = sin8((counter >> 8) & 0xFF)
+            brightness = 128 + ((pulse - 128) * seg.intensity // 255)
+            color = color_blend(0, color, brightness)
+
+        seg.set_pixel_color(i, color)
+
+    return FRAMETIME
+
+def mode_multi_strobe(seg: Segment) -> int:
+    """Multi-color strobe effect"""
+    cycle_time = 50 + (255 - seg.speed)
+    flash_duration = max(5, cycle_time // 4)
+
+    now = seg.now()
+    iteration = now // cycle_time
+    rem = now % cycle_time
+
+    if rem < flash_duration:
+        # Strobe on with color from palette
+        color_index = (iteration * 85) & 0xFF
+        color = color_wheel(color_index)
+        seg.fill(color)
+    else:
+        # Strobe off
+        seg.fill(seg.get_color(1))
+
+    return FRAMETIME
+
+def mode_waves(seg: Segment) -> int:
+    """Sine wave effect"""
+    counter = seg.now() * ((seg.speed >> 3) + 1)
+
+    for i in range(seg.length):
+        # Create wave pattern
+        wave_pos = (i * 255 // max(1, seg.length)) + (counter >> 7)
+        brightness = sin8(wave_pos & 0xFF)
+
+        # Intensity controls wave amplitude
+        brightness = 128 + ((brightness - 128) * seg.intensity // 255)
+
+        color = color_blend(seg.get_color(1),
+                          seg.color_from_palette(i),
+                          brightness)
+        seg.set_pixel_color(i, color)
+
+    return FRAMETIME
+
+def mode_bpm(seg: Segment) -> int:
+    """BPM (beats per minute) pulse effect"""
+    # Calculate BPM based on speed (60-180 BPM)
+    bpm = 60 + ((seg.speed * 120) >> 8)
+    ms_per_beat = 60000 // bpm
+
+    beat_phase = (seg.now() % ms_per_beat) * 255 // ms_per_beat
+    brightness = sin8(beat_phase)
+
+    for i in range(seg.length):
+        # Create traveling beat
+        offset = (i * 255 // max(1, seg.length))
+        local_brightness = sin8((beat_phase + offset) & 0xFF)
+
+        # Intensity controls brightness range
+        local_brightness = 128 + ((local_brightness - 128) * seg.intensity // 255)
+
+        color = color_blend(seg.get_color(1),
+                          seg.color_from_palette(i),
+                          local_brightness)
+        seg.set_pixel_color(i, color)
+
+    return FRAMETIME
+
+def mode_juggle(seg: Segment) -> int:
+    """Juggling colored dots"""
+    if seg.call == 0:
+        seg.data = [0] * 8  # Track 8 dot positions
+
+    seg.fade_out(224)
+
+    cycle_time = 10 + (255 - seg.speed) // 2
+    iteration = seg.now() // cycle_time
+
+    if iteration != seg.step:
+        # Update dot positions using different sine waves
+        for dot in range(min(8, 1 + seg.intensity // 32)):
+            phase = (seg.now() * (dot + 1)) & 0xFFFF
+            pos = (sin16(phase) + 32768) * seg.length // 65536
+            pos = max(0, min(seg.length - 1, pos))
+
+            hue = (dot * 32) & 0xFF
+            color = color_wheel(hue)
+            seg.set_pixel_color(pos, color)
+
+        seg.step = iteration
+
+    return FRAMETIME
+
 # Effect registry
 EFFECTS = {
     0: ("Static", mode_static),
@@ -320,6 +693,21 @@ EFFECTS = {
     13: ("Twinkle", mode_twinkle),
     14: ("Sparkle", mode_sparkle),
     15: ("Strobe", mode_strobe),
+    16: ("Fire", mode_fire),
+    17: ("Comet", mode_comet),
+    18: ("Chase", mode_chase),
+    19: ("Police", mode_police),
+    20: ("Lightning", mode_lightning),
+    21: ("Fireworks", mode_fireworks),
+    22: ("Ripple", mode_ripple),
+    23: ("Flow", mode_flow),
+    24: ("Colorloop", mode_colorloop),
+    25: ("Palette Flow", mode_palette_flow),
+    26: ("Gradient", mode_gradient),
+    27: ("Multi Strobe", mode_multi_strobe),
+    28: ("Waves", mode_waves),
+    29: ("BPM", mode_bpm),
+    30: ("Juggle", mode_juggle),
 }
 
 def get_effect(effect_id: int):