@@ -47,7 +47,7 @@ uint8_t Segment::_clipStopY = 1;
4747
4848// copy constructor
4949Segment::Segment (const Segment &orig) {
50- // DEBUGFX_PRINTF_P(PSTR("-- Copy segment constructor: %p -> %p\n"), &orig, this);
50+ DEBUGFX_PRINTF_P (PSTR (" -- Copy segment constructor: %p -> %p\n " ), &orig, this );
5151 memcpy ((void *)this , (void *)&orig, sizeof (Segment));
5252 _t = nullptr ; // copied segment cannot be in transition
5353 name = nullptr ;
@@ -72,7 +72,7 @@ Segment::Segment(const Segment &orig) {
7272
7373// move constructor
7474Segment::Segment (Segment &&orig) noexcept {
75- // DEBUGFX_PRINTF_P(PSTR("-- Move segment constructor: %p -> %p\n"), &orig, this);
75+ DEBUGFX_PRINTF_P (PSTR (" -- Move segment constructor: %p -> %p\n " ), &orig, this );
7676 memcpy ((void *)this , (void *)&orig, sizeof (Segment));
7777 orig._t = nullptr ; // old segment cannot be in transition any more
7878 orig.name = nullptr ;
@@ -83,7 +83,7 @@ Segment::Segment(Segment &&orig) noexcept {
8383
8484// copy assignment
8585Segment& Segment::operator = (const Segment &orig) {
86- // DEBUGFX_PRINTF_P(PSTR("-- Copying segment: %p -> %p\n"), &orig, this);
86+ DEBUGFX_PRINTF_P (PSTR (" -- Copying segment: %p -> %p\n " ), &orig, this );
8787 if (this != &orig) {
8888 // clean destination
8989 if (name) { d_free (name); name = nullptr ; }
@@ -117,7 +117,7 @@ Segment& Segment::operator= (const Segment &orig) {
117117
118118// move assignment
119119Segment& Segment::operator = (Segment &&orig) noexcept {
120- // DEBUGFX_PRINTF_P(PSTR("-- Moving segment: %p -> %p\n"), &orig, this);
120+ DEBUGFX_PRINTF_P (PSTR (" -- Moving segment: %p -> %p\n " ), &orig, this );
121121 if (this != &orig) {
122122 if (name) { d_free (name); name = nullptr ; } // free old name
123123 if (isInTransition ()) stopTransition (); // also erases _t
@@ -188,7 +188,7 @@ void Segment::deallocateData() {
188188 */
189189void Segment::resetIfRequired () {
190190 if (!reset || !isActive ()) return ;
191- // DEBUGFX_PRINTF_P(PSTR("-- Segment reset: %p\n"), this);
191+ DEBUGFX_PRINTF_P (PSTR (" -- Segment reset: %p\n " ), this );
192192 if (data && _dataLen > 0 ) memset (data, 0 , _dataLen); // prevent heap fragmentation (just erase buffer instead of deallocateData())
193193 if (_dataLen > FAIR_DATA_PER_SEG ) deallocateData (); // do not keep large allocations
194194 if (pixels) for (size_t i = 0 ; i < length (); i++) pixels[i] = hasWhite () ? BLACK : CRGBA (BLACK ); // clear pixel buffer
@@ -254,6 +254,7 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
254254
255255// starting a transition has to occur before change so we get current values 1st
256256void Segment::startTransition (uint16_t dur, bool segmentCopy) {
257+ DEBUGFX_PRINTF_P (PSTR (" -- Starting transition: %ums w/%s segment copy\n " ), (unsigned )dur, (segmentCopy ? " " : " o" ));
257258 if (dur == 0 || !isActive ()) {
258259 if (isInTransition ()) _t->_dur = 0 ;
259260 return ;
@@ -273,6 +274,7 @@ void Segment::startTransition(uint16_t dur, bool segmentCopy) {
273274 // as the JSON (or HTTP) API is processed. First call will either make a copy of segment or store original values
274275 // for colors, palettes & brightness. Subsequent calls should only modify these values if transition
275276 // has already progressed beyond 0 (or 1 frame to be exact)
277+ // _t->_progress is updated in WS2812FX::service() using handleTransition() call and changing _t->_start has no effect
276278 if (isInTransition ()) {
277279 if (segmentCopy && !_t->_oldSegment ) {
278280 // already in transition but segment copy requested and not yet created
@@ -281,38 +283,40 @@ void Segment::startTransition(uint16_t dur, bool segmentCopy) {
281283 _t->_dur = dur;
282284 _t->_prevPaletteBlends = 0 ; // reset previous palette blends
283285 if (_t->_oldSegment ) {
286+ if (!_t->_oldSegment ->isActive ()) { // even though segment's copy may be created it may lack pixel buffer
287+ stopTransition (); // in such case it will be marked inactive so stop transition entirely
288+ return ;
289+ }
290+ _t->_oldSegment ->opacity = _t->_bri ; // restore original opacity
291+ _t->_oldSegment ->cct = _t->_cct ; // restore original CCT
284292 _t->_oldSegment ->palette = _t->_palette ; // restore original palette and colors (from start of transition)
285293 for (unsigned i = 0 ; i < NUM_COLORS ; i++) _t->_oldSegment ->colors [i] = _t->_colors [i];
286- // if already partway through a FADE transition, set old segment's colors to current blend to avoid jumping back to original colors
287- if (_t->_progress > 0 )
288- for (unsigned i = 0 ; i < NUM_COLORS ; i++) _t->_oldSegment ->colors [i].nblend (colors[i], _t->_progress );
289294 DEBUGFX_PRINTF_P (PSTR (" -- Updated transition with segment copy: S=%p T(%p) O[%p] OP[%p]\n " ), this , _t, _t->_oldSegment , _t->_oldSegment ->pixels );
290- if (!_t->_oldSegment ->isActive ()) stopTransition ();
291295 } else {
292296 DEBUGFX_PRINTLN (F (" -- Error allocating memory for segment copy." ));
293297 errorFlag = ERR_NORAM ;
294298 }
295- } else if (_t->_progress > 0 ) {
299+ }
300+ if (_t->_progress > 0 ) {
296301 // If we are already in transition we need to copy current intermediate color into old color
297- // so that changing it will not produce abrup change. We will also do similar for palette.
298- // However, palette change progress is recorded in _palT (see beginDraw()).
302+ // so that changing it will not produce abrup change. We will also do similar for brightness and CCT.
303+ // However, palette change progress is recorded in _palT (see beginDraw()) so we just reset blend count.
304+ // We also need to restart transition (for all transitions!)
305+ _t->_start = millis (); // restart countdown
306+ _t->_dur = dur; // update duration
307+ _t->_prevPaletteBlends = 0 ; // reset previous palette blends
299308 if (_t->_oldSegment ) {
300309 for (unsigned i = 0 ; i < NUM_COLORS ; i++) _t->_oldSegment ->colors [i].nblend (colors[i], _t->_progress );
301310 _t->_oldSegment ->palette = _t->_palette ; // update palette and colors (from middle of transition)
311+ _t->_oldSegment ->opacity = currentBri (); // update opacity (from middle of transition)
312+ _t->_oldSegment ->cct = currentCCT (); // update CCT (from middle of transition)
302313 } else {
303314 for (unsigned i = 0 ; i < NUM_COLORS ; i++) _t->_colors [i].nblend (colors[i], _t->_progress );
304315 _t->_palette = palette; // update palette and colors (from middle of transition)
316+ _t->_bri = currentBri (); // update opacity (from middle of transition)
317+ _t->_cct = currentCCT (); // update CCT (from middle of transition)
305318 }
306- // we do the same for opacity and CCT (using methods which work correctly as we are already in transition)
307- _t->_bri = currentBri ();
308- _t->_cct = currentCCT ();
309319 DEBUGFX_PRINTF_P (PSTR (" -- Updated transition: S=%p T(%p) O[%p]\n " ), this , _t, _t->_oldSegment );
310- // we should not restart timers for non-FADE transitions
311- if (transitionStyle == TRANSITION_FADE ) {
312- _t->_start = millis (); // restart countdown
313- _t->_dur = dur; // update duration
314- _t->_prevPaletteBlends = 0 ; // reset previous palette blends
315- }
316320 }
317321 return ;
318322 }
@@ -341,7 +345,7 @@ void Segment::startTransition(uint16_t dur, bool segmentCopy) {
341345
342346void Segment::stopTransition () {
343347 DEBUGFX_PRINTF_P (PSTR (" -- Stopping transition: S=%p T(%p) O[%p]\n " ), this , _t, _t->_oldSegment );
344- delete _t;
348+ delete _t; // will also call destructor for _oldSegment and free its memory
345349 _t = nullptr ;
346350}
347351
@@ -537,7 +541,7 @@ Segment &Segment::setColor(uint8_t slot, CRGBA c) {
537541 if (slot == 0 && c == BLACK ) return *this ; // on/off segment cannot have primary color black
538542 if (slot == 1 && c != BLACK ) return *this ; // on/off segment cannot have secondary color non black
539543 }
540- // DEBUGFX_PRINTF_P(PSTR("- Starting color transition: %d [0x%X]\n"), slot, c);
544+ DEBUGFX_PRINTF_P (PSTR (" - Starting color transition: %d [0x%X]\n " ), slot, c);
541545 startTransition (strip.getTransition (), transitionStyle != TRANSITION_FADE ); // start transition prior to change
542546 colors[slot] = c;
543547 stateChanged = true ; // send UDP/WS broadcast
@@ -551,7 +555,7 @@ Segment &Segment::setCCT(uint16_t k) {
551555 k = (k - 1900 ) >> 5 ;
552556 }
553557 if (cct != k) {
554- // DEBUGFX_PRINTF_P(PSTR("- Starting CCT transition: %d\n"), k);
558+ DEBUGFX_PRINTF_P (PSTR (" - Starting CCT transition: %d\n " ), k);
555559 startTransition (strip.getTransition (), false ); // start transition prior to change (no need to copy segment)
556560 cct = k;
557561 stateChanged = true ; // send UDP/WS broadcast
@@ -561,7 +565,7 @@ Segment &Segment::setCCT(uint16_t k) {
561565
562566Segment &Segment::setOpacity (uint8_t o) {
563567 if (opacity != o) {
564- // DEBUGFX_PRINTF_P(PSTR("- Starting opacity transition: %d\n"), o);
568+ DEBUGFX_PRINTF_P (PSTR (" - Starting opacity transition: %d\n " ), o);
565569 startTransition (strip.getTransition (), transitionStyle != TRANSITION_FADE ); // start transition prior to change
566570 opacity = o;
567571 stateChanged = true ; // send UDP/WS broadcast
@@ -572,8 +576,10 @@ Segment &Segment::setOpacity(uint8_t o) {
572576Segment &Segment::setOption (uint8_t n, bool val) {
573577 bool prev = (options >> n) & 0x01 ;
574578 if (val == prev) return *this ;
575- // DEBUGFX_PRINTF_P(PSTR("- Starting option transition: %d\n"), n);
576- if (n == SEG_OPTION_ON ) startTransition (strip.getTransition (), transitionStyle != TRANSITION_FADE ); // start transition prior to change
579+ if (n == SEG_OPTION_ON ) {
580+ DEBUGFX_PRINTF_P (PSTR (" - Starting on/off transition: %d\n " ), n);
581+ startTransition (strip.getTransition (), transitionStyle != TRANSITION_FADE ); // start transition prior to change
582+ }
577583 if (val) options |= 0x01 << n;
578584 else options &= ~(0x01 << n);
579585 stateChanged = true ; // send UDP/WS broadcast
@@ -622,7 +628,7 @@ Segment &Segment::setMode(uint8_t fx, bool loadDefaults) {
622628Segment &Segment::setPalette (uint8_t pal) {
623629 if (pal <= 255 -customPalettes.size () && pal > FIXED_PALETTE_COUNT ) pal = 0 ; // not built in palette or custom palette
624630 if (pal != palette) {
625- // DEBUGFX_PRINTF_P(PSTR("- Starting palette transition: %d\n"), pal);
631+ DEBUGFX_PRINTF_P (PSTR (" - Starting palette transition: %d\n " ), pal);
626632 startTransition (strip.getTransition (), transitionStyle != TRANSITION_FADE ); // start transition prior to change (no need to copy segment)
627633 palette = pal;
628634 stateChanged = true ; // send UDP/WS broadcast
@@ -1582,6 +1588,7 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
15821588 const int oCols = segO ? segO->virtualWidth () : nCols;
15831589 const int oRows = segO ? segO->virtualHeight () : nRows;
15841590
1591+ // TODO: CCT would require same treatement as opacity (but is rare and hence not yet implemented)
15851592 const auto setMirroredPixel = [&](int x, int y, uint32_t c, uint8_t o) {
15861593 const int baseX = topSegment.start + x;
15871594 const int baseY = topSegment.startY + y;
@@ -1746,7 +1753,8 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
17461753 // if segment is in transition and pixel is clipped take old segment's pixel and opacity
17471754 // for clipped pixels use old segment's opacity (allow segment on/off/brightness transitions)
17481755 if (clipped && segO) {
1749- o = segO->currentBri ();
1756+ o = segO->on ? segO->opacity : 0 ; // old segment is never in transition (_t == nullptr) so no need for currentBri()
1757+ // cct = segO->cct; // TODO: CCT would require same treatement as opacity
17501758 _pixelsR = _pixelsO;
17511759 vCols = oCols;
17521760 vRows = oRows;
@@ -1800,6 +1808,7 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
18001808 const int nLen = topSegment.virtualLength ();
18011809 const int oLen = segO ? segO->virtualLength () : nLen;
18021810
1811+ // TODO: CCT would require same treatement as opacity (but is rare and hence not yet implemented)
18031812 const auto setMirroredPixel = [&](int i, uint32_t c, uint8_t o) {
18041813 int indx = topSegment.start + i;
18051814 // Apply mirroring
@@ -1853,7 +1862,8 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
18531862 const Segment *seg;
18541863 int vLen;
18551864 if (clipped && segO) {
1856- o = segO->currentBri ();
1865+ o = segO->on ? segO->opacity : 0 ; // old segment is never in transition (_t == nullptr) so no need for currentBri()
1866+ // cct = segO->cct; // TODO: CCT would require same treatement as opacity
18571867 vLen = oLen;
18581868 seg = segO;
18591869 } else {
0 commit comments