From 6824d7caa73c826b573858345b2f846679d951e7 Mon Sep 17 00:00:00 2001 From: Russell Stringham <45107644+RussStringham@users.noreply.github.com> Date: Thu, 9 Apr 2026 16:51:28 -0600 Subject: [PATCH 1/4] Fireworks only explode in a single color --- platformio.ini | 50 +++++++++++++++++++++++--------------------- wled00/FX.cpp | 46 +++++++++++++++++++--------------------- wled00/FX_fcn.cpp | 2 +- wled00/const.h | 2 +- wled00/data/index.js | 5 +++-- wled00/palettes.cpp | 21 ++++++++++++++++++- 6 files changed, 73 insertions(+), 53 deletions(-) diff --git a/platformio.ini b/platformio.ini index f3f5d61b06..fd2ce36aa2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,28 +10,30 @@ # ------------------------------------------------------------------------------ # CI/release binaries -default_envs = nodemcuv2 - esp8266_2m - esp01_1m_full - nodemcuv2_160 - esp8266_2m_160 - esp01_1m_full_160 - nodemcuv2_compat - esp8266_2m_compat - esp01_1m_full_compat - esp32dev - esp32dev_debug - esp32_eth - esp32_wrover - lolin_s2_mini - esp32c3dev - esp32c3dev_qio - esp32S3_wroom2 - esp32s3dev_16MB_opi - esp32s3dev_8MB_opi - esp32s3dev_8MB_qspi - esp32s3_4M_qspi - usermods +;default_envs = nodemcuv2 +; esp8266_2m +; esp01_1m_full +; nodemcuv2_160 +; esp8266_2m_160 +; esp01_1m_full_160 +; nodemcuv2_compat +; esp8266_2m_compat +; esp01_1m_full_compat +; esp32dev +; esp32dev_debug +; esp32_eth +; esp32_wrover +; lolin_s2_mini +; esp32c3dev +; esp32c3dev_qio +; esp32S3_wroom2 +; esp32s3dev_16MB_opi +; esp32s3dev_8MB_opi +; esp32s3dev_8MB_qspi +; esp32s3_4M_qspi +; usermods + +default_envs = esp32dev src_dir = ./wled00 data_dir = ./wled00/data @@ -534,7 +536,7 @@ build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_ -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue ;; Older ESP32 (rev.<3) need a PSRAM fix (increases static RAM used) https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/external-ram.html -D DATA_PINS=25 lib_deps = ${esp32_idf_V4.lib_deps} - + [env:esp32c3dev] extends = esp32c3 platform = ${esp32c3.platform} @@ -658,7 +660,7 @@ monitor_filters = esp32_exception_decoder [env:esp32s3_4M_qspi] ;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi) -board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM +board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM platform = ${esp32s3.platform} platform_packages = ${esp32s3.platform_packages} upload_speed = 921600 diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 18d61b2167..1b9caf9581 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1954,7 +1954,7 @@ void mode_colorwaves_pride_base(bool isPride2015) { unsigned msmultiplier = beatsin88_t(147, 23, 60); unsigned hue16 = sHue16; - unsigned hueinc16 = isPride2015 ? beatsin88_t(113, 1, 3000) : + unsigned hueinc16 = isPride2015 ? beatsin88_t(113, 1, 3000) : beatsin88_t(113, 60, 300) * SEGMENT.intensity * 10 / 255; sPseudotime += duration * msmultiplier; @@ -3763,7 +3763,7 @@ void mode_exploding_fireworks(void) if (SEGENV.aux0 == 0) { //init flare flare->pos = 0; flare->posX = SEGMENT.is2D() ? hw_random16(2,cols-3) : (SEGMENT.intensity > hw_random8()); // will enable random firing side on 1D - unsigned peakHeight = 75 + hw_random8(180); //0-255 + unsigned peakHeight = 84 + hw_random8(146); // 33% to 90% of 256 peakHeight = (peakHeight * (rows -1)) >> 8; flare->vel = sqrtf(-2.0f * gravity * peakHeight); flare->velX = SEGMENT.is2D() ? (hw_random8(9)-4)/64.0f : 0; // no X velocity on 1D @@ -3800,6 +3800,7 @@ void mode_exploding_fireworks(void) // initialize sparks if (SEGENV.aux0 == 2) { + int colIndex = hw_random8(); for (unsigned i = 1; i < nSparks; i++) { sparks[i].pos = flare->pos; sparks[i].posX = flare->posX; @@ -3808,7 +3809,7 @@ void mode_exploding_fireworks(void) sparks[i].velX = SEGMENT.is2D() ? (float(hw_random16(20001)) / 10000.0f) - 1.0f : 0; // from -1 to 1 sparks[i].col = 345;//abs(sparks[i].vel * 750.0); // set colors before scaling velocity to keep them bright //sparks[i].col = constrain(sparks[i].col, 0, 345); - sparks[i].colIndex = hw_random8(); + sparks[i].colIndex = colIndex; sparks[i].vel *= flare->pos/rows; // proportional to height sparks[i].velX *= SEGMENT.is2D() ? flare->posX/cols : 0; // proportional to width sparks[i].vel *= -gravity *50; @@ -3835,9 +3836,6 @@ void mode_exploding_fireworks(void) c = color_blend(spColor, WHITE, uint8_t((prog - 300)*5)); } else if (prog > 45) { //fade from spark color to black c = color_blend(BLACK, spColor, uint8_t(prog - 45)); - unsigned cooling = (300 - prog) >> 5; - c.g = qsub8(c.g, cooling); - c.b = qsub8(c.b, cooling * 2); } if (SEGMENT.is2D()) SEGMENT.setPixelColorXY(int(sparks[i].posX), rows - int(sparks[i].pos) - 1, c); else SEGMENT.setPixelColor(int(sparks[i].posX) ? rows - int(sparks[i].pos) - 1 : int(sparks[i].pos), c); @@ -4285,7 +4283,7 @@ void mode_sunrise() { for (unsigned i = 0; i <= SEGLEN/2; i++) { - //default palette is Fire + //default palette is Fire unsigned wave = triwave16((i * stage) / SEGLEN); wave = (wave >> 8) + ((wave * SEGMENT.intensity) >> 15); uint32_t c; @@ -4976,13 +4974,13 @@ void mode_ColorClouds() // Higher values make the clouds move faster. const uint32_t volSpeed = 1 + SEGMENT.speed; - + // Higher values make the color change faster. const uint32_t hueSpeed = 1 + SEGMENT.intensity; - + // Higher values make more clouds (but smaller ones). const uint32_t volSqueeze = 8 + SEGMENT.custom1; - + // Higher values make the clouds more colorful. const uint32_t hueSqueeze = SEGMENT.custom2; @@ -5352,7 +5350,7 @@ void mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline. Ye for (int j=0; j < cols; j++) { for (int i=0; i < rows; i++) { indexx = perlin8(j*yscale*rows/255, i*xscale+strip.now/4); // We're moving along our Perlin map. - SEGMENT.setPixelColorXY(j, i, ColorFromPalette(pal, min(i*indexx/11, 225U), i*255/rows, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED. + SEGMENT.setPixelColorXY(j, i, ColorFromPalette(pal, min(i*indexx/11, 225U), i*255/rows, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED. } // for i } // for j } // mode_2Dfirenoise() @@ -5386,7 +5384,7 @@ typedef struct Cell { uint8_t alive : 1, faded : 1, toggleStatus : 1, edgeCell: 1, oscillatorCheck : 1, spaceshipCheck : 1, unused : 2; } Cell; -void mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https://natureofcode.com/book/chapter-7-cellular-automata/ +void mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https://natureofcode.com/book/chapter-7-cellular-automata/ // and https://github.com/DougHaber/nlife-color , Modified By: Brandon Butler if (!strip.isMatrix || !SEGMENT.is2D()) FX_FALLBACK_STATIC; // not a 2D set-up const int cols = SEG_W, rows = SEG_H; @@ -6606,7 +6604,7 @@ void mode_2Dplasmarotozoom() { float *a = reinterpret_cast(SEGENV.data); byte *plasma = reinterpret_cast(SEGENV.data+sizeof(float)); - unsigned ms = strip.now/15; + unsigned ms = strip.now/15; // plasma for (int j = 0; j < rows; j++) { @@ -6836,7 +6834,7 @@ void mode_gravcenter_base(unsigned mode) { if(mode == 2) offset = 0; // Gravimeter if (tempsamp >= gravcen->topLED) gravcen->topLED = tempsamp-offset; else if (gravcen->gravityCounter % gravity == 0) gravcen->topLED--; - + if(mode == 1) { //Gravcentric for (int i=0; itopLED+SEGLEN/2, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0)); SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0)); } - } + } gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity; } @@ -7142,13 +7140,13 @@ void mode_puddles_base(bool peakdetect) { if (pos+size>= SEGLEN) size = SEGLEN - pos; } } - else { // puddles + else { // puddles if (volumeRaw > 1) { size = volumeRaw * SEGMENT.intensity /256 /8 + 1; // Determine size of the flash based on the volume. if (pos+size >= SEGLEN) size = SEGLEN - pos; - } + } } - + for (unsigned i=0; iapplyFriction(1); // apply friction to all particles PartSys->update(); // update and render - + for (uint32_t i = 0; i < PartSys->usedParticles; i++) { if (PartSys->particles[i].ttl > 20) PartSys->particles[i].ttl -= 20; //ttl is linked to brightness, this allows to use higher brightness but still a short spark lifespan else PartSys->particles[i].ttl = 0; @@ -11052,7 +11050,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_COLORTWINKLE, &mode_colortwinkle, _data_FX_MODE_COLORTWINKLE); addEffect(FX_MODE_LAKE, &mode_lake, _data_FX_MODE_LAKE); addEffect(FX_MODE_METEOR, &mode_meteor, _data_FX_MODE_METEOR); - //addEffect(FX_MODE_METEOR_SMOOTH, &mode_meteor_smooth, _data_FX_MODE_METEOR_SMOOTH); // merged with mode_meteor + //addEffect(FX_MODE_METEOR_SMOOTH, &mode_meteor_smooth, _data_FX_MODE_METEOR_SMOOTH); // merged with mode_meteor addEffect(FX_MODE_RAILWAY, &mode_railway, _data_FX_MODE_RAILWAY); addEffect(FX_MODE_RIPPLE, &mode_ripple, _data_FX_MODE_RIPPLE); addEffect(FX_MODE_TWINKLEFOX, &mode_twinklefox, _data_FX_MODE_TWINKLEFOX); @@ -11070,7 +11068,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_SPARKLE, &mode_sparkle, _data_FX_MODE_SPARKLE); addEffect(FX_MODE_GLITTER, &mode_glitter, _data_FX_MODE_GLITTER); addEffect(FX_MODE_SOLID_GLITTER, &mode_solid_glitter, _data_FX_MODE_SOLID_GLITTER); - addEffect(FX_MODE_MULTI_COMET, &mode_multi_comet, _data_FX_MODE_MULTI_COMET); + addEffect(FX_MODE_MULTI_COMET, &mode_multi_comet, _data_FX_MODE_MULTI_COMET); #ifdef WLED_PS_DONT_REPLACE_1D_FX addEffect(FX_MODE_ROLLINGBALLS, &mode_rolling_balls, _data_FX_MODE_ROLLINGBALLS); addEffect(FX_MODE_STARBURST, &mode_starburst, _data_FX_MODE_STARBURST); @@ -11096,7 +11094,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_SINEWAVE, &mode_sinewave, _data_FX_MODE_SINEWAVE); addEffect(FX_MODE_PHASEDNOISE, &mode_phased_noise, _data_FX_MODE_PHASEDNOISE); addEffect(FX_MODE_FLOW, &mode_flow, _data_FX_MODE_FLOW); - addEffect(FX_MODE_CHUNCHUN, &mode_chunchun, _data_FX_MODE_CHUNCHUN); + addEffect(FX_MODE_CHUNCHUN, &mode_chunchun, _data_FX_MODE_CHUNCHUN); addEffect(FX_MODE_WASHING_MACHINE, &mode_washing_machine, _data_FX_MODE_WASHING_MACHINE); addEffect(FX_MODE_BLENDS, &mode_blends, _data_FX_MODE_BLENDS); addEffect(FX_MODE_TV_SIMULATOR, &mode_tv_simulator, _data_FX_MODE_TV_SIMULATOR); diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index e538b342f6..d695c48f02 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -2099,5 +2099,5 @@ const char JSON_palette_names[] PROGMEM = R"=====([ "Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura", "Aurora","Atlantica","C9 2","C9 New","Temperature","Aurora 2","Retro Clown","Candy","Toxy Reaf","Fairy Reaf", "Semi Blue","Pink Candy","Red Reaf","Aqua Flash","Yelblu Hot","Lite Light","Red Flash","Blink Red","Red Shift","Red Tide", -"Candy2","Traffic Light" +"Candy2","Traffic Light","Fireworks" ])====="; diff --git a/wled00/const.h b/wled00/const.h index e49dd2900a..4e4cf1ae3e 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -7,7 +7,7 @@ */ constexpr size_t FASTLED_PALETTE_COUNT = 7; // 6-12 = sizeof(fastledPalettes) / sizeof(fastledPalettes[0]); -constexpr size_t GRADIENT_PALETTE_COUNT = 59; // 13-72 = sizeof(gGradientPalettes) / sizeof(gGradientPalettes[0]); +constexpr size_t GRADIENT_PALETTE_COUNT = 60; // 13-73 = sizeof(gGradientPalettes) / sizeof(gGradientPalettes[0]); constexpr size_t DYNAMIC_PALETTE_COUNT = 6; // 0- 5 = dynamic palettes (0=default(virtual),1=random,2=primary,3=primary+secondary,4=primary+secondary+tertiary,5=primary+secondary(+tertiary if not black) constexpr size_t FIXED_PALETTE_COUNT = DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT + GRADIENT_PALETTE_COUNT; // total number of fixed palettes #ifndef ESP8266 diff --git a/wled00/data/index.js b/wled00/data/index.js index b34260287e..d01b42bff7 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -2812,7 +2812,7 @@ function loadPalettesData() { if (lsPalData) { try { var d = JSON.parse(lsPalData); - if (d && d.vid == lastinfo.vid) { + if (d && d.vid == lastinfo.vid && d.pcount == lJson.length) { palettesData = d.p; redrawPalPrev(); return resolve(); @@ -2824,7 +2824,8 @@ function loadPalettesData() { getPalettesData(0, () => { localStorage.setItem("wledPalx", JSON.stringify({ p: palettesData, - vid: lastinfo.vid + vid: lastinfo.vid, + pcount: lJson.length })); redrawPalPrev(); setTimeout(resolve, 99); // delay optional diff --git a/wled00/palettes.cpp b/wled00/palettes.cpp index bcbdcf22d7..c67bbbcc76 100644 --- a/wled00/palettes.cpp +++ b/wled00/palettes.cpp @@ -759,6 +759,24 @@ const byte trafficlight_gp[] PROGMEM = { 170, 255, 255, 0, //yellow 255, 255, 0, 0}; //red +// Fireworks palette: colors sized by real-world frequency +// red/blue ~22%, green ~18%, violet ~15%, orange ~11%, white ~7%, yellow ~5% +const byte fireworks_gp[] PROGMEM = { + 0, 255, 0, 0, // red (start) + 55, 255, 0, 0, // red (end) + 56, 0, 0, 220, // blue (start) + 112, 0, 0, 220, // blue (end) + 113, 0, 210, 0, // green (start) + 158, 0, 210, 0, // green (end) + 159, 148, 0, 211, // violet (start) + 197, 148, 0, 211, // violet (end) + 198, 255, 80, 0, // orange (start) + 224, 255, 80, 0, // orange (end) + 225, 255, 255, 255, // white (start) + 243, 255, 255, 255, // white (end) + 244, 255, 210, 0, // yellow (start) + 255, 255, 210, 0}; // yellow (end) + const byte Aurora2_gp[] PROGMEM = { 0, 17, 177, 13, //Greenish 64, 121, 242, 5, //Greenish @@ -863,5 +881,6 @@ const uint8_t* const gGradientPalettes[] PROGMEM = { red_shift_gp, //68-55 Red Shift red_tide_gp, //69-56 Red Tide candy2_gp, //70-57 Candy2 - trafficlight_gp //71-58 Traffic Light + trafficlight_gp, //71-58 Traffic Light + fireworks_gp //72-59 Fireworks }; \ No newline at end of file From fa589997ee4a7dfadb5a23c501ae0c7874ce6cdc Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:12:17 +0200 Subject: [PATCH 2/4] revert platformio.ini changes we need to know if all buidenv compile without error - otherwie this PR cannot get merged. --- platformio.ini | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/platformio.ini b/platformio.ini index fd2ce36aa2..f3f5d61b06 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,30 +10,28 @@ # ------------------------------------------------------------------------------ # CI/release binaries -;default_envs = nodemcuv2 -; esp8266_2m -; esp01_1m_full -; nodemcuv2_160 -; esp8266_2m_160 -; esp01_1m_full_160 -; nodemcuv2_compat -; esp8266_2m_compat -; esp01_1m_full_compat -; esp32dev -; esp32dev_debug -; esp32_eth -; esp32_wrover -; lolin_s2_mini -; esp32c3dev -; esp32c3dev_qio -; esp32S3_wroom2 -; esp32s3dev_16MB_opi -; esp32s3dev_8MB_opi -; esp32s3dev_8MB_qspi -; esp32s3_4M_qspi -; usermods - -default_envs = esp32dev +default_envs = nodemcuv2 + esp8266_2m + esp01_1m_full + nodemcuv2_160 + esp8266_2m_160 + esp01_1m_full_160 + nodemcuv2_compat + esp8266_2m_compat + esp01_1m_full_compat + esp32dev + esp32dev_debug + esp32_eth + esp32_wrover + lolin_s2_mini + esp32c3dev + esp32c3dev_qio + esp32S3_wroom2 + esp32s3dev_16MB_opi + esp32s3dev_8MB_opi + esp32s3dev_8MB_qspi + esp32s3_4M_qspi + usermods src_dir = ./wled00 data_dir = ./wled00/data @@ -536,7 +534,7 @@ build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_ -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue ;; Older ESP32 (rev.<3) need a PSRAM fix (increases static RAM used) https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/external-ram.html -D DATA_PINS=25 lib_deps = ${esp32_idf_V4.lib_deps} - + [env:esp32c3dev] extends = esp32c3 platform = ${esp32c3.platform} @@ -660,7 +658,7 @@ monitor_filters = esp32_exception_decoder [env:esp32s3_4M_qspi] ;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi) -board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM +board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM platform = ${esp32s3.platform} platform_packages = ${esp32s3.platform_packages} upload_speed = 921600 From 4f6bdb373b21fa424211dc4bd26133a64ca53ed8 Mon Sep 17 00:00:00 2001 From: Russell Stringham <45107644+RussStringham@users.noreply.github.com> Date: Fri, 10 Apr 2026 10:01:13 -0600 Subject: [PATCH 3/4] restore trailing whitespace --- wled00/FX.cpp | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 1b9caf9581..26ed7d1203 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1954,7 +1954,7 @@ void mode_colorwaves_pride_base(bool isPride2015) { unsigned msmultiplier = beatsin88_t(147, 23, 60); unsigned hue16 = sHue16; - unsigned hueinc16 = isPride2015 ? beatsin88_t(113, 1, 3000) : + unsigned hueinc16 = isPride2015 ? beatsin88_t(113, 1, 3000) : beatsin88_t(113, 60, 300) * SEGMENT.intensity * 10 / 255; sPseudotime += duration * msmultiplier; @@ -4283,7 +4283,7 @@ void mode_sunrise() { for (unsigned i = 0; i <= SEGLEN/2; i++) { - //default palette is Fire + //default palette is Fire unsigned wave = triwave16((i * stage) / SEGLEN); wave = (wave >> 8) + ((wave * SEGMENT.intensity) >> 15); uint32_t c; @@ -4974,13 +4974,13 @@ void mode_ColorClouds() // Higher values make the clouds move faster. const uint32_t volSpeed = 1 + SEGMENT.speed; - + // Higher values make the color change faster. const uint32_t hueSpeed = 1 + SEGMENT.intensity; - + // Higher values make more clouds (but smaller ones). const uint32_t volSqueeze = 8 + SEGMENT.custom1; - + // Higher values make the clouds more colorful. const uint32_t hueSqueeze = SEGMENT.custom2; @@ -5350,7 +5350,7 @@ void mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline. Ye for (int j=0; j < cols; j++) { for (int i=0; i < rows; i++) { indexx = perlin8(j*yscale*rows/255, i*xscale+strip.now/4); // We're moving along our Perlin map. - SEGMENT.setPixelColorXY(j, i, ColorFromPalette(pal, min(i*indexx/11, 225U), i*255/rows, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED. + SEGMENT.setPixelColorXY(j, i, ColorFromPalette(pal, min(i*indexx/11, 225U), i*255/rows, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED. } // for i } // for j } // mode_2Dfirenoise() @@ -5384,7 +5384,7 @@ typedef struct Cell { uint8_t alive : 1, faded : 1, toggleStatus : 1, edgeCell: 1, oscillatorCheck : 1, spaceshipCheck : 1, unused : 2; } Cell; -void mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https://natureofcode.com/book/chapter-7-cellular-automata/ +void mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https://natureofcode.com/book/chapter-7-cellular-automata/ // and https://github.com/DougHaber/nlife-color , Modified By: Brandon Butler if (!strip.isMatrix || !SEGMENT.is2D()) FX_FALLBACK_STATIC; // not a 2D set-up const int cols = SEG_W, rows = SEG_H; @@ -6604,7 +6604,7 @@ void mode_2Dplasmarotozoom() { float *a = reinterpret_cast(SEGENV.data); byte *plasma = reinterpret_cast(SEGENV.data+sizeof(float)); - unsigned ms = strip.now/15; + unsigned ms = strip.now/15; // plasma for (int j = 0; j < rows; j++) { @@ -6834,7 +6834,7 @@ void mode_gravcenter_base(unsigned mode) { if(mode == 2) offset = 0; // Gravimeter if (tempsamp >= gravcen->topLED) gravcen->topLED = tempsamp-offset; else if (gravcen->gravityCounter % gravity == 0) gravcen->topLED--; - + if(mode == 1) { //Gravcentric for (int i=0; itopLED+SEGLEN/2, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0)); SEGMENT.setPixelColor(SEGLEN/2-1-gravcen->topLED, SEGMENT.color_from_palette(strip.now, false, PALETTE_SOLID_WRAP, 0)); } - } + } gravcen->gravityCounter = (gravcen->gravityCounter + 1) % gravity; } @@ -7140,13 +7140,13 @@ void mode_puddles_base(bool peakdetect) { if (pos+size>= SEGLEN) size = SEGLEN - pos; } } - else { // puddles + else { // puddles if (volumeRaw > 1) { size = volumeRaw * SEGMENT.intensity /256 /8 + 1; // Determine size of the flash based on the volume. if (pos+size >= SEGLEN) size = SEGLEN - pos; - } + } } - + for (unsigned i=0; iapplyFriction(1); // apply friction to all particles PartSys->update(); // update and render - + for (uint32_t i = 0; i < PartSys->usedParticles; i++) { if (PartSys->particles[i].ttl > 20) PartSys->particles[i].ttl -= 20; //ttl is linked to brightness, this allows to use higher brightness but still a short spark lifespan else PartSys->particles[i].ttl = 0; @@ -11050,7 +11050,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_COLORTWINKLE, &mode_colortwinkle, _data_FX_MODE_COLORTWINKLE); addEffect(FX_MODE_LAKE, &mode_lake, _data_FX_MODE_LAKE); addEffect(FX_MODE_METEOR, &mode_meteor, _data_FX_MODE_METEOR); - //addEffect(FX_MODE_METEOR_SMOOTH, &mode_meteor_smooth, _data_FX_MODE_METEOR_SMOOTH); // merged with mode_meteor + //addEffect(FX_MODE_METEOR_SMOOTH, &mode_meteor_smooth, _data_FX_MODE_METEOR_SMOOTH); // merged with mode_meteor addEffect(FX_MODE_RAILWAY, &mode_railway, _data_FX_MODE_RAILWAY); addEffect(FX_MODE_RIPPLE, &mode_ripple, _data_FX_MODE_RIPPLE); addEffect(FX_MODE_TWINKLEFOX, &mode_twinklefox, _data_FX_MODE_TWINKLEFOX); @@ -11068,7 +11068,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_SPARKLE, &mode_sparkle, _data_FX_MODE_SPARKLE); addEffect(FX_MODE_GLITTER, &mode_glitter, _data_FX_MODE_GLITTER); addEffect(FX_MODE_SOLID_GLITTER, &mode_solid_glitter, _data_FX_MODE_SOLID_GLITTER); - addEffect(FX_MODE_MULTI_COMET, &mode_multi_comet, _data_FX_MODE_MULTI_COMET); + addEffect(FX_MODE_MULTI_COMET, &mode_multi_comet, _data_FX_MODE_MULTI_COMET); #ifdef WLED_PS_DONT_REPLACE_1D_FX addEffect(FX_MODE_ROLLINGBALLS, &mode_rolling_balls, _data_FX_MODE_ROLLINGBALLS); addEffect(FX_MODE_STARBURST, &mode_starburst, _data_FX_MODE_STARBURST); @@ -11094,7 +11094,7 @@ void WS2812FX::setupEffectData() { addEffect(FX_MODE_SINEWAVE, &mode_sinewave, _data_FX_MODE_SINEWAVE); addEffect(FX_MODE_PHASEDNOISE, &mode_phased_noise, _data_FX_MODE_PHASEDNOISE); addEffect(FX_MODE_FLOW, &mode_flow, _data_FX_MODE_FLOW); - addEffect(FX_MODE_CHUNCHUN, &mode_chunchun, _data_FX_MODE_CHUNCHUN); + addEffect(FX_MODE_CHUNCHUN, &mode_chunchun, _data_FX_MODE_CHUNCHUN); addEffect(FX_MODE_WASHING_MACHINE, &mode_washing_machine, _data_FX_MODE_WASHING_MACHINE); addEffect(FX_MODE_BLENDS, &mode_blends, _data_FX_MODE_BLENDS); addEffect(FX_MODE_TV_SIMULATOR, &mode_tv_simulator, _data_FX_MODE_TV_SIMULATOR); From 85924f7b34fd545c1b8133e0d718a89e4e70056f Mon Sep 17 00:00:00 2001 From: Russell Stringham <45107644+RussStringham@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:05:23 -0600 Subject: [PATCH 4/4] Add a "single color" checkmark option --- wled00/FX.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 26ed7d1203..6f32d86542 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -3800,7 +3800,7 @@ void mode_exploding_fireworks(void) // initialize sparks if (SEGENV.aux0 == 2) { - int colIndex = hw_random8(); + int colIndex = hw_random8(); // single color: one index shared by all sparks for (unsigned i = 1; i < nSparks; i++) { sparks[i].pos = flare->pos; sparks[i].posX = flare->posX; @@ -3809,7 +3809,7 @@ void mode_exploding_fireworks(void) sparks[i].velX = SEGMENT.is2D() ? (float(hw_random16(20001)) / 10000.0f) - 1.0f : 0; // from -1 to 1 sparks[i].col = 345;//abs(sparks[i].vel * 750.0); // set colors before scaling velocity to keep them bright //sparks[i].col = constrain(sparks[i].col, 0, 345); - sparks[i].colIndex = colIndex; + sparks[i].colIndex = SEGMENT.check1 ? colIndex : hw_random8(); // single color: share one index; otherwise random per spark sparks[i].vel *= flare->pos/rows; // proportional to height sparks[i].velX *= SEGMENT.is2D() ? flare->posX/cols : 0; // proportional to width sparks[i].vel *= -gravity *50; @@ -3836,6 +3836,11 @@ void mode_exploding_fireworks(void) c = color_blend(spColor, WHITE, uint8_t((prog - 300)*5)); } else if (prog > 45) { //fade from spark color to black c = color_blend(BLACK, spColor, uint8_t(prog - 45)); + if (!SEGMENT.check1) { // without single color, shift toward red/orange as sparks cool + unsigned cooling = (300 - prog) >> 5; + c.g = qsub8(c.g, cooling); + c.b = qsub8(c.b, cooling * 2); + } } if (SEGMENT.is2D()) SEGMENT.setPixelColorXY(int(sparks[i].posX), rows - int(sparks[i].pos) - 1, c); else SEGMENT.setPixelColor(int(sparks[i].posX) ? rows - int(sparks[i].pos) - 1 : int(sparks[i].pos), c); @@ -3854,7 +3859,7 @@ void mode_exploding_fireworks(void) } } #undef MAX_SPARKS -static const char _data_FX_MODE_EXPLODING_FIREWORKS[] PROGMEM = "Fireworks 1D@Gravity,Firing side;!,!;!;12;pal=11,ix=128"; +static const char _data_FX_MODE_EXPLODING_FIREWORKS[] PROGMEM = "Fireworks 1D@Gravity,Firing side,,,,Single Color;!,!;!;12;pal=11,ix=128"; #endif // WLED_PS_DONT_REPLACE_x_FX /*