Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 86 additions & 1 deletion wled00/FX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5268,7 +5268,6 @@ void mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline. Ye
unsigned yscale = SEGMENT.speed*8;
unsigned indexx = 0;

//CRGBPalette16 pal = SEGMENT.check1 ? SEGPALETTE : SEGMENT.loadPalette(pal, 35);
CRGBPalette16 pal = SEGMENT.check1 ? SEGPALETTE : CRGBPalette16(CRGB::Black, CRGB::Black, CRGB::Black, CRGB::Black,
CRGB::Red, CRGB::Red, CRGB::Red, CRGB::DarkOrange,
CRGB::DarkOrange,CRGB::DarkOrange, CRGB::Orange, CRGB::Orange,
Expand Down Expand Up @@ -10718,6 +10717,91 @@ static const char _data_FX_MODE_PS_SPRINGY[] PROGMEM = "PS Springy@Stiffness,Dam

#endif // WLED_DISABLE_PARTICLESYSTEM1D

/*
* Slow Transition effect
* Displays the currently selected palette/color with a very slow transition
* speed slider controls the number of minutes for the transition (0 = 10s)
* after transition completes, applies preset set by intensity slider (if any)
* allows for chains of slow transitions just like a playlist
* by DedeHai
*/
typedef struct SlowTransitionData {
CRGBPalette16 startPalette; // initial palette
CRGBPalette16 currentPalette; // blended palette for current frame, need permanent storage so we can start from this if target changes mid transition
CRGBPalette16 endPalette; // target palette
} slow_transition_data;

void mode_slow_transition(void) {
// aliases
uint32_t* startTime = &SEGMENT.step; // use step to store start time of transition
uint16_t* stepsDone = &SEGMENT.aux0;
uint16_t* startSpeed = &SEGMENT.aux1; // speed setting at the start of the transition, used to detect changes

size_t dataSize = sizeof(slow_transition_data);
if (!SEGMENT.allocateData(dataSize)) FX_FALLBACK_STATIC;
slow_transition_data* data = reinterpret_cast<slow_transition_data*>(SEGMENT.data);

bool changed = (data->endPalette != SEGPALETTE || *startSpeed != SEGMENT.speed); // detect changes in target palette or speed setting

// (re) init
if (changed || SEGMENT.call == 0) {
if (SEGMENT.call == 0) {
//data->presetapplied = false;
data->startPalette = SEGPALETTE;
data->currentPalette = SEGPALETTE;
data->endPalette = SEGPALETTE;
*stepsDone = 0xFFFF; // set to max, fading will start once a change is detected
}
else {
data->startPalette = data->currentPalette;
data->endPalette = SEGPALETTE;
*stepsDone = 0; // reset counter
}
*startSpeed = SEGMENT.speed;
*startTime = strip.now; // set start time
}

uint32_t totalSteps = SEGMENT.check2 ? 16 * 255 : 255;
uint32_t duration = (SEGMENT.speed == 0) ? 10000 : (uint32_t)SEGMENT.speed * 60000; // 10s if zero (good for testing), otherwise map 1-255 to 1-255 minutes
uint32_t elapsed = strip.now - *startTime; // note: will overflow after ~50 days if just left alone (edge case unhandled)
uint32_t expectedSteps = (uint64_t)elapsed * totalSteps / duration;
expectedSteps = min(expectedSteps, totalSteps); // limit to total steps

if (*stepsDone > expectedSteps)
*stepsDone = expectedSteps;// in case sweep was disabled mid transition

if (*stepsDone < expectedSteps) {
*stepsDone = expectedSteps; // jump to expected steps to make sure timing is correct (need up to 4080 frames, at 20fps that is ~200 seconds)
if (SEGMENT.check2) {
// sweep: one palette entry at a time
uint8_t i = *stepsDone % 16;
uint8_t blendAmount = *stepsDone / 16;
data->currentPalette[i] = CRGB(color_blend(CRGBW(data->startPalette[i]), CRGBW(data->endPalette[i]), blendAmount));
} else {
// full palette at once
uint8_t blendAmount = (uint8_t)*stepsDone;
for (uint8_t i = 0; i < 16; i++) {
data->currentPalette[i] = CRGB(color_blend(CRGBW(data->startPalette[i]), CRGBW(data->endPalette[i]), blendAmount));
}
}
if (*stepsDone >= totalSteps) {
// transition complete, apply preset set by intensity slider (if any)
data->currentPalette = data->endPalette; // set to end palette (sweep may not have set all entries)
if (SEGMENT.intensity > 0) {
uint8_t targetPreset = SEGMENT.intensity;
applyPreset(targetPreset, CALL_MODE_DIRECT_CHANGE); // apply preset (if it exists)
}
}
}
// display current palette over segment
for (unsigned i = 0; i < SEGLEN; i++) {
uint8_t paletteIndex = (i * 255) / SEGLEN;
CRGBW palcol = ColorFromPaletteWLED(data->currentPalette, paletteIndex, 255, LINEARBLEND_NOWRAP);
SEGMENT.setPixelColor(i, palcol.color32);
}
}
static const char _data_FX_MODE_SLOW_TRANSITION[] PROGMEM = "Slow Transition@Time (min), End reset,,,,,Sweep;3;!;0;pal=2,sx=0,ix=0";

//////////////////////////////////////////////////////////////////////////////////////////
// mode data
static const char _data_RESERVED[] PROGMEM = "RSVD";
Expand Down Expand Up @@ -10880,6 +10964,7 @@ void WS2812FX::setupEffectData() {
addEffect(FX_MODE_TV_SIMULATOR, &mode_tv_simulator, _data_FX_MODE_TV_SIMULATOR);
addEffect(FX_MODE_DYNAMIC_SMOOTH, &mode_dynamic_smooth, _data_FX_MODE_DYNAMIC_SMOOTH);
addEffect(FX_MODE_PACMAN, &mode_pacman, _data_FX_MODE_PACMAN);
addEffect(FX_MODE_SLOW_TRANSITION, &mode_slow_transition, _data_FX_MODE_SLOW_TRANSITION);

// --- 1D audio effects ---
addEffect(FX_MODE_PIXELS, &mode_pixels, _data_FX_MODE_PIXELS);
Expand Down
5 changes: 3 additions & 2 deletions wled00/FX.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,8 @@ extern byte realtimeMode; // used in getMappedPixelIndex()
#define FX_MODE_PS1DSONICBOOM 215
#define FX_MODE_PS1DSPRINGY 216
#define FX_MODE_PARTICLEGALAXY 217
#define MODE_COUNT 218
#define FX_MODE_SLOW_TRANSITION 218
#define MODE_COUNT 219


#define BLEND_STYLE_FADE 0x00 // universal
Expand Down Expand Up @@ -547,7 +548,7 @@ class Segment {
inline uint32_t getPixelColorXYRaw(unsigned x, unsigned y) const { auto XY = [](unsigned X, unsigned Y){ return X + Y*Segment::vWidth(); }; return pixels[XY(x,y)]; };
#endif
void resetIfRequired(); // sets all SEGENV variables to 0 and clears data buffer
CRGBPalette16 &loadPalette(CRGBPalette16 &tgt, uint8_t pal);
void loadPalette(CRGBPalette16 &tgt, uint8_t pal);

// transition functions
void stopTransition(); // ends transition mode by destroying transition structure (does nothing if not in transition)
Expand Down
7 changes: 3 additions & 4 deletions wled00/FX_fcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,8 @@ void Segment::resetIfRequired() {
#endif
}

CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
// there is one randomy generated palette (1) followed by 4 palettes created from segment colors (2-5)
void Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
// there is one randomly generated palette (1) followed by 4 palettes created from segment colors (2-5)
// those are followed by 7 fastled palettes (6-12) and 59 gradient palettes (13-71)
// then come the custom palettes (255,254,...) growing downwards from 255 (255 being 1st custom palette)
// palette 0 is a varying palette depending on effect and may be replaced by segment's color if so
Expand Down Expand Up @@ -277,7 +277,6 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
}
break;
}
return targetPalette;
}

// starting a transition has to occur before change so we get current values 1st
Expand Down Expand Up @@ -577,7 +576,7 @@ Segment &Segment::setMode(uint8_t fx, bool loadDefaults) {
sOpt = extractModeDefaults(fx, "pal"); // always extract 'pal' to set _default_palette
if (sOpt >= 0 && loadDefaults) setPalette(sOpt);
if (sOpt <= 0) sOpt = 6; // partycolors if zero or not set
_default_palette = sOpt; // _deault_palette is loaded into pal0 in loadPalette() (if selected)
_default_palette = sOpt; // _default_palette is loaded into pal0 in loadPalette() (if selected)
markForReset();
stateChanged = true; // send UDP/WS broadcast
}
Expand Down