use smart_leds_trait::RGB8;
use crate::segment::{EffectConfig, EffectState};
use crate::utils::{BLACK, color_wheel, fade_out, next_rand, rand_wheel_index};
pub fn twinkle(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
let len = pixels.len() as u32;
if state.counter == 0 {
for p in pixels.iter_mut() {
*p = config.colors[1];
}
let min = len / 4 + 1;
let rng = next_rand(state.aux);
state.aux = rng;
state.counter = min + (rng % min);
}
let rng = next_rand(state.aux);
state.aux = rng;
pixels[(rng % len) as usize] = config.colors[0];
state.counter = state.counter.saturating_sub(1);
}
pub fn twinkle_random(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
if state.counter == 0 {
let rng = next_rand(state.aux);
state.aux = rng;
let wheel_idx = rng as u8;
let len = pixels.len() as u32;
let min = len / 4 + 1;
let rng2 = next_rand(rng);
state.aux = rng2;
let count = min + (rng2 % min);
state.counter = count | ((wheel_idx as u32) << 24);
for p in pixels.iter_mut() {
*p = config.colors[1];
}
}
let wheel_idx = (state.counter >> 24) as u8;
let fg = color_wheel(wheel_idx);
let rng = next_rand(state.aux);
state.aux = rng;
pixels[(rng % pixels.len() as u32) as usize] = fg;
let count = state.counter & 0x00FF_FFFF;
state.counter = (count.saturating_sub(1)) | ((wheel_idx as u32) << 24);
}
pub fn twinkle_fade(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
fade_out(pixels, BLACK, 64);
let rng = next_rand(state.aux);
state.aux = next_rand(rng);
if rng % 3 == 0 {
let idx = (state.aux % pixels.len() as u32) as usize;
pixels[idx] = config.colors[0];
}
}
pub fn twinkle_fade_random(pixels: &mut [RGB8], state: &mut EffectState, _config: &EffectConfig) {
fade_out(pixels, BLACK, 64);
let rng = next_rand(state.aux);
state.aux = next_rand(rng);
if rng % 3 == 0 {
let idx = (state.aux % pixels.len() as u32) as usize;
pixels[idx] = color_wheel(rng as u8);
}
}
pub fn sparkle(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
let len = pixels.len() as u32;
if state.aux == 0 {
for p in pixels.iter_mut() {
*p = config.colors[0];
}
} else {
pixels[state.counter as usize] = config.colors[0];
}
let rng = next_rand(state.aux);
state.aux = rng;
let idx = (rng % len) as usize;
pixels[idx] = config.colors[1];
state.counter = idx as u32;
}
pub fn flash_sparkle(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
let len = pixels.len() as u32;
if state.aux == 0 {
for p in pixels.iter_mut() {
*p = config.colors[0];
}
} else {
pixels[state.counter as usize] = config.colors[0];
}
let rng = next_rand(state.aux);
state.aux = rng;
let idx = (rng % len) as usize;
pixels[idx] = crate::utils::WHITE;
state.counter = idx as u32;
}
pub fn sparkle_random(pixels: &mut [RGB8], state: &mut EffectState, _config: &EffectConfig) {
let len = pixels.len() as u32;
let wheel_idx = (state.aux & 0xFF) as u8;
let prev_pos = ((state.aux >> 8) & 0xFF) as usize;
let rng = state.aux >> 16;
if state.counter == 0 {
let (new_idx, new_rng) = rand_wheel_index(wheel_idx, rng);
let bg = color_wheel(new_idx.wrapping_add(128));
for p in pixels.iter_mut() {
*p = bg;
}
let rng2 = next_rand(new_rng);
let new_pos = (rng2 % len) as usize;
pixels[new_pos] = color_wheel(new_idx);
state.aux = new_idx as u32 | ((new_pos as u32) << 8) | (rng2 << 16);
} else {
pixels[prev_pos] = color_wheel(wheel_idx.wrapping_add(128));
let new_rng = next_rand(rng);
let new_pos = (new_rng % len) as usize;
pixels[new_pos] = color_wheel(wheel_idx);
state.aux = wheel_idx as u32 | ((new_pos as u32) << 8) | (new_rng << 16);
}
state.counter = state.counter.wrapping_add(1);
}