diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 5bc6f848d..a7cff4aaf 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4244,6 +4244,8 @@ uint16_t WS2812FX::mode_aurora(void) { // Black hole uint16_t WS2812FX::mode_2DBlackHole(void) { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline + if (!isMatrix) return mode_static(); // not a 2D set-up + uint16_t w = SEGMENT.virtualWidth(); uint16_t h = SEGMENT.virtualHeight(); uint16_t dataSize = sizeof(CRGB) * w * h; @@ -4260,19 +4262,23 @@ uint16_t WS2812FX::mode_2DBlackHole(void) { // By: Stepko https://edi } } - fadeToBlackBy(leds, 32); // create fading trails - float t = (float)(millis())/128; + fadeToBlackBy(leds, 16 + (SEGMENT.speed>>3)); // create fading trails + float t = (float)(millis())/128; // timebase + // inner stars for (byte i = 0; i < 8; i++) { - x = beatsin8(SEGMENT.c1x>>3, 0, w - 1, 0, ((i % 2) ? 128 : 0) + t * i); - y = beatsin8(10 , 0, h - 1, 0, ((i % 2) ? 192 : 64) + t * i); + x = beatsin8(SEGMENT.c1x>>3, 0, w - 1, 0, ((i % 2) ? 128 : 0) + t * i); + y = beatsin8(SEGMENT.intensity>>3, 0, h - 1, 0, ((i % 2) ? 192 : 64) + t * i); leds[XY(x,y)] += CHSV(i*32, 255, 255); } + // outer stars for (byte i = 0; i < 8; i++) { x = beatsin8(SEGMENT.c2x>>3, w/4, w - 1 - w/4, 0, ((i % 2) ? 128 : 0) + t * i); y = beatsin8(SEGMENT.c3x>>3, h/4, h - 1 - h/4, 0, ((i % 2) ? 192 : 64) + t * i); leds[XY(x,y)] += CHSV(i*32, 255, 255); } + // central white dot leds[XY(w/2,h/2)] = CHSV(0,0,255); + // blur everything a bit blur2d(leds, 16); for (y = 0; y < h; y++) for (x = 0; x < w; x++) { @@ -4286,6 +4292,8 @@ uint16_t WS2812FX::mode_2DBlackHole(void) { // By: Stepko https://edi // 2D DNA // ///////////////////// uint16_t WS2812FX::mode_2Ddna(void) { // dna originally by by ldirko at https://pastebin.com/pCkkkzcs. Updated by Preyy. WLED conversion by Andrew Tuline. + if (!isMatrix) return mode_static(); // not a 2D set-up + uint16_t width = SEGMENT.virtualWidth(); uint16_t height = SEGMENT.virtualHeight(); uint16_t dataSize = sizeof(CRGB) * width * height; @@ -4311,6 +4319,8 @@ uint16_t WS2812FX::mode_2Ddna(void) { // dna originally by by ldirko at // 2D DNA Spiral // ///////////////////////// uint16_t WS2812FX::mode_2DDNASpiral() { // By: ldirko https://editor.soulmatelights.com/gallery/810 , modified by: Andrew Tuline + if (!isMatrix) return mode_static(); // not a 2D set-up + uint16_t width = SEGMENT.virtualWidth(); uint16_t height = SEGMENT.virtualHeight(); uint16_t dataSize = sizeof(CRGB) * width * height; @@ -4351,6 +4361,8 @@ uint16_t WS2812FX::mode_2DDNASpiral() { // By: ldirko https://edi // 2D Drift // ///////////////////////// uint16_t WS2812FX::mode_2DDrift() { // By: Stepko https://editor.soulmatelights.com/gallery/884-drift , Modified by: Andrew Tuline + if (!isMatrix) return mode_static(); // not a 2D set-up + uint16_t width = SEGMENT.virtualWidth(); uint16_t height = SEGMENT.virtualHeight(); uint16_t dataSize = sizeof(CRGB) * width * height; @@ -4379,6 +4391,8 @@ uint16_t WS2812FX::mode_2DDrift() { // By: Stepko https://editor. // 2D Firenoise // ////////////////////////// uint16_t WS2812FX::mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline. Yet another short routine. + if (!isMatrix) return mode_static(); // not a 2D set-up + uint16_t width = SEGMENT.virtualWidth(); uint16_t height = SEGMENT.virtualHeight(); uint16_t dataSize = sizeof(CRGB) * width * height; @@ -4410,6 +4424,8 @@ uint16_t WS2812FX::mode_2Dfirenoise(void) { // firenoise2d. By And // 2D Frizzles // ////////////////////////////// uint16_t WS2812FX::mode_2DFrizzles(void) { // By: Stepko https://editor.soulmatelights.com/gallery/640-color-frizzles , Modified by: Andrew Tuline + if (!isMatrix) return mode_static(); // not a 2D set-up + uint16_t width = SEGMENT.virtualWidth(); uint16_t height = SEGMENT.virtualHeight(); uint16_t dataSize = sizeof(CRGB) * width * height; @@ -4435,6 +4451,8 @@ uint16_t WS2812FX::mode_2DFrizzles(void) { // By: Stepko https:/ // 2D Hiphotic // ///////////////////////// uint16_t WS2812FX::mode_2DHiphotic() { // By: ldirko https://editor.soulmatelights.com/gallery/810 , Modified by: Andrew Tuline + if (!isMatrix) return mode_static(); // not a 2D set-up + uint16_t width = SEGMENT.virtualWidth(); uint16_t height = SEGMENT.virtualHeight(); uint16_t dataSize = sizeof(CRGB) * width * height; @@ -4462,6 +4480,8 @@ uint16_t WS2812FX::mode_2DHiphotic() { // By: ldirko ht // 2D Lissajous // ////////////////////////////// uint16_t WS2812FX::mode_2DLissajous(void) { // By: Andrew Tuline + if (!isMatrix) return mode_static(); // not a 2D set-up + uint16_t width = SEGMENT.virtualWidth(); uint16_t height = SEGMENT.virtualHeight(); uint16_t dataSize = sizeof(CRGB) * width * height; @@ -4490,6 +4510,8 @@ uint16_t WS2812FX::mode_2DLissajous(void) { // By: Andrew Tuline // 2D Matrix // /////////////////////// uint16_t WS2812FX::mode_2Dmatrix(void) { // Matrix2D. By Jeremy Williams. Adapted by Andrew Tuline & improved by merkisoft and ewowi. + if (!isMatrix) return mode_static(); // not a 2D set-up + uint16_t width = SEGMENT.virtualWidth(); uint16_t height = SEGMENT.virtualHeight(); uint16_t dataSize = sizeof(CRGB) * width * height; @@ -4550,6 +4572,8 @@ uint16_t WS2812FX::mode_2Dmatrix(void) { // Matrix2D. By Jeremy } // mode_2Dmatrix() uint16_t WS2812FX::mode_2DAkemi(void) { + if (!isMatrix) return mode_static(); // not a 2D set-up + uint16_t width = SEGMENT.virtualWidth(); uint16_t height = SEGMENT.virtualHeight(); diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 8865a3c8e..59edf4c7c 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -138,21 +138,19 @@ void IRAM_ATTR WS2812FX::setPixelColorXY(uint16_t x, uint16_t y, byte r, byte g, } uint32_t col = RGBW32(r, g, b, w); - uint16_t width = SEGMENT.virtualWidth(); // segment width in logical pixels (includes grouping, spacing, mirror & transposed) - uint16_t height = SEGMENT.virtualHeight(); // segment height in logical pixels (includes grouping, spacing, mirror & transposed) if (SEGMENT.getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed - x *= SEGMENT.groupLength(); - y *= SEGMENT.groupLength(); - if (x >= width || y >= height) return; // if pixel would fall out of segment just exit + x *= SEGMENT.groupLength(); // expand to physical pixels + y *= SEGMENT.groupLength(); // expand to physical pixels + if (x >= SEGMENT.width() || y >= SEGMENT.height()) return; // if pixel would fall out of segment just exit - for (uint8_t j = 0; j < SEGMENT.grouping; j++) { // groupping vertically - for (uint8_t g = 0; g < SEGMENT.grouping; g++) { // groupping horizontally + for (uint8_t j = 0; j < SEGMENT.grouping; j++) { // groupping vertically + for (uint8_t g = 0; g < SEGMENT.grouping; g++) { // groupping horizontally uint16_t index, xX = (x+g), yY = (y+j); if (xX >= SEGMENT.width() || yY >= SEGMENT.height()) continue; // we have reached one dimension's end - if (SEGMENT.getOption(SEG_OPTION_REVERSED) ) xX = width - xX - 1; - if (SEGMENT.getOption(SEG_OPTION_REVERSED_Y)) yY = height - yY - 1; + if (SEGMENT.getOption(SEG_OPTION_REVERSED) ) xX = SEGMENT.width() - xX - 1; + if (SEGMENT.getOption(SEG_OPTION_REVERSED_Y)) yY = SEGMENT.height() - yY - 1; index = getPixelIndex(xX, yY); if (index < customMappingSize) index = customMappingTable[index]; @@ -172,19 +170,16 @@ void IRAM_ATTR WS2812FX::setPixelColorXY(uint16_t x, uint16_t y, byte r, byte g, } } - -uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) -{ - uint16_t width = SEGMENT.virtualWidth(); // segment width in logical pixels - uint16_t height = SEGMENT.virtualHeight(); // segment height in logical pixels +// not working correctly ATM +uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) { if (SEGMENT.getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed - x *= SEGMENT.groupLength(); - y *= SEGMENT.groupLength(); + x *= SEGMENT.groupLength(); // expand to physical pixels + y *= SEGMENT.groupLength(); // expand to physical pixels if (x >= SEGMENT.width() || y >= SEGMENT.height()) return 0; - if (SEGMENT.getOption(SEG_OPTION_REVERSED) ) x = width - x - 1; - if (SEGMENT.getOption(SEG_OPTION_REVERSED_Y)) y = height - y - 1; + if (SEGMENT.getOption(SEG_OPTION_REVERSED) ) x = SEGMENT.width() - x - 1; + if (SEGMENT.getOption(SEG_OPTION_REVERSED_Y)) y = SEGMENT.height() - y - 1; uint16_t index = getPixelIndex(x, y); if (index < customMappingSize) index = customMappingTable[index]; @@ -194,48 +189,44 @@ uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) // blurRows: perform a blur1d on every row of a rectangular matrix -void WS2812FX::blurRow(uint16_t y, fract8 blur_amount, CRGB* leds) -{ +void WS2812FX::blurRow(uint16_t row, fract8 blur_amount, CRGB* leds) { uint16_t width = SEGMENT.virtualWidth(); + uint16_t height = SEGMENT.virtualHeight(); + if (row >= height) return; + // blur one row uint8_t keep = 255 - blur_amount; uint8_t seep = blur_amount >> 1; CRGB carryover = CRGB::Black; for (uint16_t x = 0; x < width; x++) { - CRGB cur = leds ? leds[XY(x,y)] : col_to_crgb(getPixelColorXY(x,y)); + CRGB cur = leds[XY(x,row)]; CRGB part = cur; part.nscale8(seep); cur.nscale8(keep); cur += carryover; - if (x) { - if (leds) leds[XY((x-1),y)] += part; - else setPixelColorXY(x-1, y, col_to_crgb(getPixelColorXY(x-1, y)) + part); - } - if (leds) leds[XY(x,y)] = cur; - else setPixelColorXY(x, y, cur); + if (x) leds[XY(x-1,row)] += part; + leds[XY(x,row)] = cur; carryover = part; } } // blurColumns: perform a blur1d on each column of a rectangular matrix -void WS2812FX::blurCol(uint16_t x, fract8 blur_amount, CRGB* leds) +void WS2812FX::blurCol(uint16_t col, fract8 blur_amount, CRGB* leds) { + uint16_t width = SEGMENT.virtualWidth(); uint16_t height = SEGMENT.virtualHeight(); - // blur columns + if (col >= width) return; + // blur one column uint8_t keep = 255 - blur_amount; uint8_t seep = blur_amount >> 1; CRGB carryover = CRGB::Black; - for ( uint16_t y = 0; y < height; y++) { - CRGB cur = leds ? leds[XY(x,y)] : col_to_crgb(getPixelColorXY(x,y)); + for (uint16_t i = 0; i < height; i++) { + CRGB cur = leds[XY(col,i)]; CRGB part = cur; part.nscale8(seep); cur.nscale8(keep); cur += carryover; - if (y) { - if (leds) leds[XY(x,(y-1))] += part; - else setPixelColorXY(x, y-1, col_to_crgb(getPixelColorXY(x,y-1)) + part); - } - if (leds) leds[XY(x,y)] = cur; - else setPixelColorXY(x, y, cur); + if (i) leds[XY(col,i-1)] += part; + leds[XY(col,i)] = cur; carryover = part; } } @@ -254,44 +245,16 @@ void WS2812FX::blurCol(uint16_t x, fract8 blur_amount, CRGB* leds) // eventually all the way to black; this is by design so that // it can be used to (slowly) clear the LEDs to black. -void WS2812FX::blur1d(CRGB* leds, fract8 blur_amount) -{ +void WS2812FX::blur1d(CRGB* leds, fract8 blur_amount) { uint16_t height = SEGMENT.virtualHeight(); - for ( uint16_t y = 0; y < height; y++) - blurRow(y, blur_amount, leds); + for (uint16_t y = 0; y < height; y++) blurRow(y, blur_amount, leds); } -void WS2812FX::blur2d(CRGB* leds, fract8 blur_amount) -{ - uint16_t w = SEGMENT.virtualWidth(); // same as SEGLEN - uint16_t h = SEGMENT.virtualHeight(); - uint8_t keep = 255 - blur_amount; - uint8_t seep = blur_amount >> 1; - for (uint16_t k = 0; k < h; k++) { - CRGB carryover = CRGB::Black; - for(uint16_t i = 0; i < w; i++) { - CRGB cur = leds ? leds[XY(i,k)] : col_to_crgb(getPixelColorXY(i, k)); - CRGB part = cur; - part.nscale8(seep); - cur.nscale8(keep); - cur += carryover; - if (i > 0) { - CRGB c = leds ? leds[XY(i,k)] : col_to_crgb(getPixelColorXY(i-1, k)); - c += part; - if (leds) leds[XY(i-1,k)] = c; - else setPixelColorXY(i-1, k, c.red, c.green, c.blue); - } - // seep from previous row - if (k > 0) { - CRGB c = col_to_crgb(getPixelColorXY(i, k-1)); - c.nscale8(seep); - cur += c; - } - if (leds) leds[XY(i,k)] = cur; - else setPixelColorXY(i, k, cur.red, cur.green, cur.blue); - carryover = part; - } - } +void WS2812FX::blur2d(CRGB* leds, fract8 blur_amount) { + uint16_t width = SEGMENT.virtualWidth(); // same as SEGLEN + uint16_t height = SEGMENT.virtualHeight(); + for (uint16_t i = 0; i < height; i++) blurRow(i, blur_amount, leds); // blur all rows + for (uint16_t k = 0; k < width; k++) blurCol(k, blur_amount, leds); // blur all columns } //ewowi20210628: new functions moved from colorutils: add segment awareness diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index ec4470ae8..90bb0e42e 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1432,7 +1432,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Blends@Shift speed,Blend speed;1,2,3,!", "TV Simulator", "Dynamic Smooth", -"2D Black Hole@!,!,Inner X,Outer X,Outer Y;!,!,!;!", +"2D Black Hole@Fade rate,Inner Y freq,Inner X freq,Outer X freq,Outer Y freq;!,!,!;!", "2D DNA", "2D DNA Spiral", "2D Drift",