Segment layering & effect blending improvements

- Photoshop-style segment/layer blending
- return of strip ABL
- remove global LED buffer in favour of segment-local buffer
- new effect blending modes/transitions
- custom palettes moved out of WS2812FX class
- increased limits (matrix size, LED RAM)
- added "rainbow"-mode colorwheel
- replaced palettes with gamma unmodified ones
- move gamma adjustment to last step before sending to LEDs
- Segment & WS2812FX class reorganisation (mutable members, reordered members, protected members)
This commit is contained in:
Blaž Kristan
2025-04-22 22:37:18 +02:00
parent 353868414a
commit ee9ac947a1
32 changed files with 2723 additions and 2931 deletions

View File

@@ -4,11 +4,9 @@
* LED methods
*/
void setValuesFromMainSeg() { setValuesFromSegment(strip.getMainSegmentId()); }
void setValuesFromFirstSelectedSeg() { setValuesFromSegment(strip.getFirstSelectedSegId()); }
void setValuesFromSegment(uint8_t s)
{
Segment& seg = strip.getSegment(s);
// applies chosen setment properties to legacy values
void setValuesFromSegment(uint8_t s) {
const Segment& seg = strip.getSegment(s);
colPri[0] = R(seg.colors[0]);
colPri[1] = G(seg.colors[0]);
colPri[2] = B(seg.colors[0]);
@@ -24,25 +22,19 @@ void setValuesFromSegment(uint8_t s)
}
// applies global legacy values (col, colSec, effectCurrent...)
// problem: if the first selected segment already has the value to be set, other selected segments are not updated
void applyValuesToSelectedSegs()
{
// copy of first selected segment to tell if value was updated
unsigned firstSel = strip.getFirstSelectedSegId();
Segment selsegPrev = strip.getSegment(firstSel);
// applies global legacy values (colPri, colSec, effectCurrent...) to each selected segment
void applyValuesToSelectedSegs() {
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue;
if (effectSpeed != selsegPrev.speed) {seg.speed = effectSpeed; stateChanged = true;}
if (effectIntensity != selsegPrev.intensity) {seg.intensity = effectIntensity; stateChanged = true;}
if (effectPalette != selsegPrev.palette) {seg.setPalette(effectPalette);}
if (effectCurrent != selsegPrev.mode) {seg.setMode(effectCurrent);}
if (!(seg.isActive() && seg.isSelected())) continue;
if (effectSpeed != seg.speed) {seg.speed = effectSpeed; stateChanged = true;}
if (effectIntensity != seg.intensity) {seg.intensity = effectIntensity; stateChanged = true;}
if (effectPalette != seg.palette) {seg.setPalette(effectPalette);}
if (effectCurrent != seg.mode) {seg.setMode(effectCurrent);}
uint32_t col0 = RGBW32(colPri[0], colPri[1], colPri[2], colPri[3]);
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0);}
if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1);}
if (col0 != seg.colors[0]) {seg.setColor(0, col0);}
if (col1 != seg.colors[1]) {seg.setColor(1, col1);}
}
}
@@ -73,7 +65,8 @@ byte scaledBri(byte in)
//applies global temporary brightness (briT) to strip
void applyBri() {
if (!(realtimeMode && arlsForceMaxBri)) {
if (realtimeOverride || !(realtimeMode && arlsForceMaxBri))
{
//DEBUG_PRINTF_P(PSTR("Applying strip brightness: %d (%d,%d)\n"), (int)briT, (int)bri, (int)briOld);
strip.setBrightness(scaledBri(briT));
}
@@ -94,7 +87,7 @@ void applyFinalBri() {
void stateUpdated(byte callMode) {
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa 11: ws send only 12: button preset
setValuesFromFirstSelectedSeg();
setValuesFromFirstSelectedSeg(); // a much better approach would be to use main segment: setValuesFromMainSeg()
if (bri != briOld || stateChanged) {
if (stateChanged) currentPreset = 0; //something changed, so we are no longer in the preset
@@ -104,7 +97,6 @@ void stateUpdated(byte callMode) {
//set flag to update ws and mqtt
interfaceUpdateCallMode = callMode;
stateChanged = false;
} else {
if (nightlightActive && !nightlightActiveOld && callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) {
notify(CALL_MODE_NIGHTLIGHT);
@@ -134,15 +126,16 @@ void stateUpdated(byte callMode) {
jsonTransitionOnce = false;
transitionActive = false;
applyFinalBri();
return;
strip.trigger();
} else {
if (transitionActive) {
briOld = briT;
} else if (bri != briOld || stateChanged)
strip.setTransitionMode(true); // force all segments to transition mode
transitionActive = true;
transitionStartTime = now;
}
if (transitionActive) {
briOld = briT;
} else
strip.setTransitionMode(true); // force all segments to transition mode
transitionActive = true;
transitionStartTime = now;
stateChanged = false;
}