From aee9c4a193467f9bc850f1a2991cb7938bfc2f52 Mon Sep 17 00:00:00 2001 From: Steve Pomeroy Date: Sat, 22 Aug 2020 14:54:59 -0400 Subject: [PATCH 1/2] Add Dancing Shadows effect --- wled00/FX.cpp | 151 +++++++++++++++++++++++++++++++++++++++++++++++++- wled00/FX.h | 11 +++- 2 files changed, 158 insertions(+), 4 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index c74c113b..5c351ed6 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -3563,4 +3563,153 @@ uint16_t WS2812FX::mode_chunchun(void) setPixelColor(bird, c); } return FRAMETIME; -} \ No newline at end of file +} + +typedef struct Spotlight { + float speed; + uint8_t colorIdx; + int16_t position; + unsigned long lastUpdateTime; + uint8_t width; + uint8_t type; +} spotlight; + +static const uint8_t SPOT_TYPE_SOLID = 0; +static const uint8_t SPOT_TYPE_GRADIENT = 1; +static const uint8_t SPOT_TYPE_2X_GRADIENT = 2; +static const uint8_t SPOT_TYPE_2X_DOT = 3; +static const uint8_t SPOT_TYPE_3X_DOT = 4; +static const uint8_t SPOT_TYPE_4X_DOT = 5; +static const uint8_t SPOT_TYPES_COUNT = 6; + +/* + * Blends the specified color with the existing pixel color. + */ +void WS2812FX::blendPixelColor(uint16_t n, uint32_t color, uint8_t blend) +{ + setPixelColor(n, color_blend(getPixelColor(n), color, blend)); +} + +/* + * Spotlights moving back and forth that cast dancing shadows. + * Shine this through tree branches/leaves or other close-up objects that cast + * interesting shadows onto a ceiling or tarp. + * + * By Steve Pomeroy @xxv + */ +uint16_t WS2812FX::mode_dancing_shadows(void) +{ + uint8_t numSpotlights = map(SEGMENT.intensity, 0, 255, 2, 50); + bool initialize = SEGENV.aux0 != numSpotlights; + SEGENV.aux0 = numSpotlights; + + uint16_t dataSize = sizeof(spotlight) * numSpotlights; + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + Spotlight* spotlights = reinterpret_cast(SEGENV.data); + + fill(BLACK); + + unsigned long time = millis(); + bool respawn = false; + + for (uint8_t i = 0; i < numSpotlights; i++) { + if (!initialize) { + // advance the position of the spotlight + int16_t delta = (float)(time - spotlights[i].lastUpdateTime) * + (spotlights[i].speed * ((1.0 + SEGMENT.speed)/100.0)); + + if (abs(delta) >= 1) { + spotlights[i].position += delta; + spotlights[i].lastUpdateTime = time; + } + + respawn = (spotlights[i].speed > 0.0 && spotlights[i].position > (SEGLEN + 2)) + || (spotlights[i].speed < 0.0 && spotlights[i].position < -(spotlights[i].width + 2)); + } + + if (initialize || respawn) { + spotlights[i].colorIdx = random8(); + spotlights[i].width = random8(1, 10); + + spotlights[i].speed = 1.0/random8(4, 50); + + if (initialize) { + spotlights[i].position = random16(SEGLEN); + spotlights[i].speed *= random8(2) ? 1.0 : -1.0; + } else { + if (random8(2)) { + spotlights[i].position = SEGLEN + spotlights[i].width; + spotlights[i].speed *= -1.0; + }else { + spotlights[i].position = -spotlights[i].width; + } + } + + spotlights[i].lastUpdateTime = time; + spotlights[i].type = random8(SPOT_TYPES_COUNT); + } + + uint32_t color = color_from_palette(spotlights[i].colorIdx, false, false, 0); + int start = spotlights[i].position; + + if (spotlights[i].width <= 1) { + if (start >= 0 && start < SEGLEN) { + blendPixelColor(start, color, 128); + } + } else { + switch (spotlights[i].type) { + case SPOT_TYPE_SOLID: + for (uint8_t j = 0; j < spotlights[i].width; j++) { + if ((start + j) >= 0 && (start + j) < SEGLEN) { + blendPixelColor(start + j, color, 128); + } + } + break; + + case SPOT_TYPE_GRADIENT: + for (uint8_t j = 0; j < spotlights[i].width; j++) { + if ((start + j) >= 0 && (start + j) < SEGLEN) { + blendPixelColor(start + j, color, + cubicwave8(map(j, 0, spotlights[i].width - 1, 0, 255))); + } + } + break; + + case SPOT_TYPE_2X_GRADIENT: + for (uint8_t j = 0; j < spotlights[i].width; j++) { + if ((start + j) >= 0 && (start + j) < SEGLEN) { + blendPixelColor(start + j, color, + cubicwave8(2 * map(j, 0, spotlights[i].width - 1, 0, 255))); + } + } + break; + + case SPOT_TYPE_2X_DOT: + for (uint8_t j = 0; j < spotlights[i].width; j += 2) { + if ((start + j) >= 0 && (start + j) < SEGLEN) { + blendPixelColor(start + j, color, 128); + } + } + break; + + case SPOT_TYPE_3X_DOT: + for (uint8_t j = 0; j < spotlights[i].width; j += 3) { + if ((start + j) >= 0 && (start + j) < SEGLEN) { + blendPixelColor(start + j, color, 128); + } + } + break; + + case SPOT_TYPE_4X_DOT: + for (uint8_t j = 0; j < spotlights[i].width; j += 4) { + if ((start + j) >= 0 && (start + j) < SEGLEN) { + blendPixelColor(start + j, color, 128); + } + } + break; + } + } + } + + return FRAMETIME; +} diff --git a/wled00/FX.h b/wled00/FX.h index 5cfda350..dde41f63 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -101,7 +101,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED ) == SELECTED ) -#define MODE_COUNT 112 +#define MODE_COUNT 113 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -215,6 +215,7 @@ #define FX_MODE_PHASEDNOISE 109 #define FX_MODE_FLOW 110 #define FX_MODE_CHUNCHUN 111 +#define FX_MODE_DANCING_SHADOWS 112 class WS2812FX { typedef uint16_t (WS2812FX::*mode_ptr)(void); @@ -418,6 +419,7 @@ class WS2812FX { _mode[FX_MODE_PHASEDNOISE] = &WS2812FX::mode_phased_noise; _mode[FX_MODE_FLOW] = &WS2812FX::mode_flow; _mode[FX_MODE_CHUNCHUN] = &WS2812FX::mode_chunchun; + _mode[FX_MODE_DANCING_SHADOWS] = &WS2812FX::mode_dancing_shadows; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -613,7 +615,8 @@ class WS2812FX { mode_sinewave(void), mode_phased_noise(void), mode_flow(void), - mode_chunchun(void); + mode_chunchun(void), + mode_dancing_shadows(void); private: NeoPixelWrapper *bus; @@ -665,6 +668,8 @@ class WS2812FX { CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat); CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff); + + void blendPixelColor(uint16_t n, uint32_t color, uint8_t blend); uint32_t _lastPaletteChange = 0; uint32_t _lastShow = 0; @@ -701,7 +706,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst", "Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent","Ripple Rainbow", "Heartbeat","Pacifica","Candle Multi", "Solid Glitter","Sunrise","Phased","Twinkleup","Noise Pal", "Sine","Phased Noise", -"Flow","Chunchun" +"Flow","Chunchun","Dancing Shadows" ])====="; From 20f6378a3e8d71afb9d3a7366aaabc4047bb667c Mon Sep 17 00:00:00 2001 From: cschwinne Date: Sun, 30 Aug 2020 10:57:42 +0200 Subject: [PATCH 2/2] Move blendPixelColor() to FX_fcn.cpp --- wled00/FX.cpp | 23 ++++++++--------------- wled00/FX_fcn.cpp | 8 ++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 5c351ed6..88e55be0 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -3565,6 +3565,7 @@ uint16_t WS2812FX::mode_chunchun(void) return FRAMETIME; } + typedef struct Spotlight { float speed; uint8_t colorIdx; @@ -3574,21 +3575,13 @@ typedef struct Spotlight { uint8_t type; } spotlight; -static const uint8_t SPOT_TYPE_SOLID = 0; -static const uint8_t SPOT_TYPE_GRADIENT = 1; -static const uint8_t SPOT_TYPE_2X_GRADIENT = 2; -static const uint8_t SPOT_TYPE_2X_DOT = 3; -static const uint8_t SPOT_TYPE_3X_DOT = 4; -static const uint8_t SPOT_TYPE_4X_DOT = 5; -static const uint8_t SPOT_TYPES_COUNT = 6; - -/* - * Blends the specified color with the existing pixel color. - */ -void WS2812FX::blendPixelColor(uint16_t n, uint32_t color, uint8_t blend) -{ - setPixelColor(n, color_blend(getPixelColor(n), color, blend)); -} +#define SPOT_TYPE_SOLID 0 +#define SPOT_TYPE_GRADIENT 1 +#define SPOT_TYPE_2X_GRADIENT 2 +#define SPOT_TYPE_2X_DOT 3 +#define SPOT_TYPE_3X_DOT 4 +#define SPOT_TYPE_4X_DOT 5 +#define SPOT_TYPES_COUNT 6 /* * Spotlights moving back and forth that cast dancing shadows. diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index f9c1fef9..5abe3790 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -597,6 +597,14 @@ void WS2812FX::fill(uint32_t c) { } } +/* + * Blends the specified color with the existing pixel color. + */ +void WS2812FX::blendPixelColor(uint16_t n, uint32_t color, uint8_t blend) +{ + setPixelColor(n, color_blend(getPixelColor(n), color, blend)); +} + /* * fade out function, higher rate = quicker fade */