Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ class RotaryEncoderBrightnessColor : public Usermod
}
else
{
fastled_col.red = col[0];
fastled_col.green = col[1];
fastled_col.blue = col[2];
fastled_col.red = colPri[0];
fastled_col.green = colPri[1];
fastled_col.blue = colPri[2];
prim_hsv = rgb2hsv_approximate(fastled_col);
new_val = (int16_t)prim_hsv.h + fadeAmount;
if (new_val > 255)
Expand All @@ -106,9 +106,9 @@ class RotaryEncoderBrightnessColor : public Usermod
new_val += 255; // roll-over if smaller than 0
prim_hsv.h = (byte)new_val;
hsv2rgb_rainbow(prim_hsv, fastled_col);
col[0] = fastled_col.red;
col[1] = fastled_col.green;
col[2] = fastled_col.blue;
colPri[0] = fastled_col.red;
colPri[1] = fastled_col.green;
colPri[2] = fastled_col.blue;
}
}
else if (Enc_B == LOW)
Expand All @@ -120,9 +120,9 @@ class RotaryEncoderBrightnessColor : public Usermod
}
else
{
fastled_col.red = col[0];
fastled_col.green = col[1];
fastled_col.blue = col[2];
fastled_col.red = colPri[0];
fastled_col.green = colPri[1];
fastled_col.blue = colPri[2];
prim_hsv = rgb2hsv_approximate(fastled_col);
new_val = (int16_t)prim_hsv.h - fadeAmount;
if (new_val > 255)
Expand All @@ -131,9 +131,9 @@ class RotaryEncoderBrightnessColor : public Usermod
new_val += 255; // roll-over if smaller than 0
prim_hsv.h = (byte)new_val;
hsv2rgb_rainbow(prim_hsv, fastled_col);
col[0] = fastled_col.red;
col[1] = fastled_col.green;
col[2] = fastled_col.blue;
colPri[0] = fastled_col.red;
colPri[1] = fastled_col.green;
colPri[2] = fastled_col.blue;
}
}
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ void RotaryEncoderUIUsermod::setup()

loopTime = millis();

currentCCT = (approximateKelvinFromRGB(RGBW32(col[0], col[1], col[2], col[3])) - 1900) >> 5;
currentCCT = (approximateKelvinFromRGB(RGBW32(colPri[0], colPri[1], colPri[2], colPri[3])) - 1900) >> 5;

if (!initDone) sortModesAndPalettes();

Expand Down Expand Up @@ -920,17 +920,17 @@ void RotaryEncoderUIUsermod::changeHue(bool increase){
display->updateRedrawTime();
#endif
currentHue1 = max(min((increase ? currentHue1+fadeAmount : currentHue1-fadeAmount), 255), 0);
colorHStoRGB(currentHue1*256, currentSat1, col);
colorHStoRGB(currentHue1*256, currentSat1, colPri);
stateChanged = true;
if (applyToAll) {
for (unsigned i=0; i<strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue;
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
seg.colors[0] = RGBW32(colPri[0], colPri[1], colPri[2], colPri[3]);
}
} else {
Segment& seg = strip.getSegment(strip.getMainSegmentId());
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
seg.colors[0] = RGBW32(colPri[0], colPri[1], colPri[2], colPri[3]);
}
lampUdated();
#ifdef USERMOD_FOUR_LINE_DISPLAY
Expand All @@ -950,16 +950,16 @@ void RotaryEncoderUIUsermod::changeSat(bool increase){
display->updateRedrawTime();
#endif
currentSat1 = max(min((increase ? currentSat1+fadeAmount : currentSat1-fadeAmount), 255), 0);
colorHStoRGB(currentHue1*256, currentSat1, col);
colorHStoRGB(currentHue1*256, currentSat1, colPri);
if (applyToAll) {
for (unsigned i=0; i<strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (!seg.isActive()) continue;
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
seg.colors[0] = RGBW32(colPri[0], colPri[1], colPri[2], colPri[3]);
}
} else {
Segment& seg = strip.getSegment(strip.getMainSegmentId());
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
seg.colors[0] = RGBW32(colPri[0], colPri[1], colPri[2], colPri[3]);
}
lampUdated();
#ifdef USERMOD_FOUR_LINE_DISPLAY
Expand Down
2 changes: 1 addition & 1 deletion wled00/FX.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ typedef struct Segment {
static void handleRandomPalette();
inline static const CRGBPalette16 &getCurrentPalette() { return Segment::_currentPalette; }

void setGeometry(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1);
void setGeometry(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1, uint8_t m12 = 0);
Segment &setColor(uint8_t slot, uint32_t c);
Segment &setCCT(uint16_t k);
Segment &setOpacity(uint8_t o);
Expand Down
65 changes: 28 additions & 37 deletions wled00/FX_fcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,19 +456,24 @@ void Segment::handleRandomPalette() {
}

// segId is given when called from network callback, changes are queued if that segment is currently in its effect function
void Segment::setGeometry(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t ofs, uint16_t i1Y, uint16_t i2Y) {
void Segment::setGeometry(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t ofs, uint16_t i1Y, uint16_t i2Y, uint8_t m12) {
// return if neither bounds nor grouping have changed
bool boundsUnchanged = (start == i1 && stop == i2);
#ifndef WLED_DISABLE_2D
if (Segment::maxHeight>1) boundsUnchanged &= (startY == i1Y && stopY == i2Y); // 2D
#endif

m12 = constrain(m12, 0, 7);
if (stop && (spc > 0 || m12 != map1D2D)) fill(BLACK);
if (m12 != map1D2D) map1D2D = m12;
/*
if (boundsUnchanged
&& (!grp || (grouping == grp && spacing == spc))
&& (ofs == UINT16_MAX || ofs == offset)) return;

&& (m12 == map1D2D)
) return;
*/
stateChanged = true; // send UDP/WS broadcast

if (stop) fill(BLACK); // turn old segment range off (clears pixels if changing spacing)
if (grp) { // prevent assignment of 0
grouping = grp;
spacing = spc;
Expand All @@ -478,10 +483,7 @@ void Segment::setGeometry(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, ui
}
if (ofs < UINT16_MAX) offset = ofs;

DEBUG_PRINT(F("setUp segment: ")); DEBUG_PRINT(i1);
DEBUG_PRINT(','); DEBUG_PRINT(i2);
DEBUG_PRINT(F(" -> ")); DEBUG_PRINT(i1Y);
DEBUG_PRINT(','); DEBUG_PRINTLN(i2Y);
DEBUG_PRINTF_P(PSTR("Segment geometry: %d,%d -> %d,%d\n"), (int)i1, (int)i2, (int)i1Y, (int)i2Y);
markForReset();
if (boundsUnchanged) return;

Expand Down Expand Up @@ -1061,36 +1063,25 @@ void Segment::fade_out(uint8_t rate) {
const int cols = is2D() ? virtualWidth() : virtualLength();
const int rows = virtualHeight(); // will be 1 for 1D

rate = (255-rate) >> 1;
float mappedRate = 1.0f / (float(rate) + 1.1f);

uint32_t color = colors[1]; // SEGCOLOR(1); // target color
int w2 = W(color);
int r2 = R(color);
int g2 = G(color);
int b2 = B(color);
rate = (256-rate) >> 1;
const int mappedRate = 256 / (rate + 1);

for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x);
uint32_t color = is2D() ? getPixelColorXY(x, y) : getPixelColor(x);
if (color == colors[1]) continue; // already at target color
int w1 = W(color);
int r1 = R(color);
int g1 = G(color);
int b1 = B(color);

int wdelta = (w2 - w1) * mappedRate;
int rdelta = (r2 - r1) * mappedRate;
int gdelta = (g2 - g1) * mappedRate;
int bdelta = (b2 - b1) * mappedRate;

// if fade isn't complete, make sure delta is at least 1 (fixes rounding issues)
wdelta += (w2 == w1) ? 0 : (w2 > w1) ? 1 : -1;
rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1;
gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1;
bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1;

if (is2D()) setPixelColorXY(x, y, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
else setPixelColor(x, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
for (int i = 0; i < 32; i += 8) {
uint8_t c2 = (colors[1]>>i); // get background channel
uint8_t c1 = (color>>i); // get foreground channel
// we can't use bitshift since we are using int
int delta = (c2 - c1) * mappedRate / 256;
// if fade isn't complete, make sure delta is at least 1 (fixes rounding issues)
if (delta == 0) delta += (c2 == c1) ? 0 : (c2 > c1) ? 1 : -1;
// stuff new value back into color
color &= ~(0xFF<<i);
color |= ((c1 + delta) & 0xFF) << i;
}
if (is2D()) setPixelColorXY(x, y, color);
else setPixelColor(x, color);
}
}

Expand Down Expand Up @@ -1364,7 +1355,7 @@ void WS2812FX::service() {
_segment_index = 0;

for (segment &seg : _segments) {
if (_suspend) return; // immediately stop processing segments if suspend requested during service()
if (_suspend) break; // immediately stop processing segments if suspend requested during service()

// process transition (mode changes in the middle of transition)
seg.handleTransition();
Expand Down Expand Up @@ -1429,8 +1420,8 @@ void WS2812FX::service() {
if (doShow) {
yield();
Segment::handleRandomPalette(); // slowly transition random palette; move it into for loop when each segment has individual random palette
show();
_lastServiceShow = nowUp; // update timestamp, for precise FPS control
if (!_suspend) show();
}
#ifdef WLED_DEBUG
if ((_targetFps != FPS_UNLIMITED) && (millis() - nowUp > _frametime)) DEBUG_PRINTF_P(PSTR("Slow strip %u/%d.\n"), (unsigned)(millis()-nowUp), (int)_frametime);
Expand Down
4 changes: 2 additions & 2 deletions wled00/button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void longPressAction(uint8_t b)
{
if (!macroLongPress[b]) {
switch (b) {
case 0: setRandomColor(col); colorUpdated(CALL_MODE_BUTTON); break;
case 0: setRandomColor(colPri); colorUpdated(CALL_MODE_BUTTON); break;
case 1:
if(buttonBriDirection) {
if (bri == 255) break; // avoid unnecessary updates to brightness
Expand Down Expand Up @@ -230,7 +230,7 @@ void handleAnalog(uint8_t b)
effectPalette = constrain(effectPalette, 0, strip.getPaletteCount()-1); // map is allowed to "overshoot", so we need to contrain the result
} else if (macroDoublePress[b] == 200) {
// primary color, hue, full saturation
colorHStoRGB(aRead*256,255,col);
colorHStoRGB(aRead*256,255,colPri);
} else {
// otherwise use "double press" for segment selection
Segment& seg = strip.getSegment(macroDoublePress[b]);
Expand Down
40 changes: 22 additions & 18 deletions wled00/data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -773,8 +773,8 @@ function populateSegments(s)
}

let segp = `<div id="segp${i}" class="sbs">`+
`<i class="icons slider-icon pwr ${inst.on ? "act":""}" id="seg${i}pwr" onclick="setSegPwr(${i})">&#xe08f;</i>`+
`<div class="sliderwrap il">`+
`<i class="icons slider-icon pwr ${inst.on ? "act":""}" id="seg${i}pwr" title="Power" onclick="setSegPwr(${i})">&#xe08f;</i>`+
`<div class="sliderwrap il" title="Opacity/Brightness">`+
`<input id="seg${i}bri" class="noslide" onchange="setSegBri(${i})" oninput="updateTrail(this)" max="255" min="1" type="range" value="${inst.bri}" />`+
`<div class="sliderdisplay"></div>`+
`</div>`+
Expand Down Expand Up @@ -810,7 +810,7 @@ function populateSegments(s)
cn += `<div class="seg lstI ${i==s.mainseg && !simplifiedUI ? 'selected' : ''} ${exp ? "expanded":""}" id="seg${i}" data-set="${inst.set}">`+
`<label class="check schkl ${smpl}">`+
`<input type="checkbox" id="seg${i}sel" onchange="selSeg(${i})" ${inst.sel ? "checked":""}>`+
`<span class="checkmark"></span>`+
`<span class="checkmark" title="Select"></span>`+
`</label>`+
`<div class="segname ${smpl}" onclick="selSegEx(${i})">`+
`<i class="icons e-icon frz" id="seg${i}frz" title="(un)Freeze" onclick="event.preventDefault();tglFreeze(${i});">&#x${inst.frz ? (li.live && li.liveseg==i?'e410':'e0e8') : 'e325'};</i>`+
Expand Down Expand Up @@ -1659,13 +1659,17 @@ function setEffectParameters(idx)
paOnOff[0] = paOnOff[0].substring(0,dPos);
}
if (paOnOff.length>0 && paOnOff[0] != "!") text = paOnOff[0];
gId("adPal").classList.remove("hide");
if (lastinfo.cpalcount>0) gId("rmPal").classList.remove("hide");
} else {
// disable palette list
text += ' not used';
palw.style.display = "none";
gId("adPal").classList.add("hide");
gId("rmPal").classList.add("hide");
// Close palette dialog if not available
if (gId("palw").lastElementChild.tagName == "DIALOG") {
gId("palw").lastElementChild.close();
if (palw.lastElementChild.tagName == "DIALOG") {
palw.lastElementChild.close();
}
}
pall.innerHTML = icon + text;
Expand Down Expand Up @@ -1879,7 +1883,7 @@ function makeSeg()
function resetUtil(off=false)
{
gId('segutil').innerHTML = `<div class="seg btn btn-s${off?' off':''}" style="padding:0;margin-bottom:12px;">`
+ '<label class="check schkl"><input type="checkbox" id="selall" onchange="selSegAll(this)"><span class="checkmark"></span></label>'
+ '<label class="check schkl"><input type="checkbox" id="selall" onchange="selSegAll(this)"><span class="checkmark" title="Select all"></span></label>'
+ `<div class="segname" ${off?'':'onclick="makeSeg()"'}><i class="icons btn-icon">&#xe18a;</i>Add segment</div>`
+ '<div class="pop hide" onclick="event.stopPropagation();">'
+ `<i class="icons g-icon" title="Select group" onclick="this.nextElementSibling.classList.toggle('hide');">&#xE34B;</i>`
Expand Down Expand Up @@ -2649,36 +2653,36 @@ function fromRgb()
var g = gId('sliderG').value;
var b = gId('sliderB').value;
setPicker(`rgb(${r},${g},${b})`);
let cd = gId('csl').children; // color slots
cd[csel].dataset.r = r;
cd[csel].dataset.g = g;
cd[csel].dataset.b = b;
setCSL(cd[csel]);
let cd = gId('csl').children[csel]; // color slots
cd.dataset.r = r;
cd.dataset.g = g;
cd.dataset.b = b;
setCSL(cd);
}

function fromW()
{
let w = gId('sliderW');
let cd = gId('csl').children; // color slots
cd[csel].dataset.w = w.value;
setCSL(cd[csel]);
let cd = gId('csl').children[csel]; // color slots
cd.dataset.w = w.value;
setCSL(cd);
updateTrail(w);
}

// sr 0: from RGB sliders, 1: from picker, 2: from hex
function setColor(sr)
{
var cd = gId('csl').children; // color slots
let cdd = cd[csel].dataset;
let w = 0, r,g,b;
var cd = gId('csl').children[csel]; // color slots
let cdd = cd.dataset;
let w = parseInt(cdd.w), r = parseInt(cdd.r), g = parseInt(cdd.g), b = parseInt(cdd.b);
if (sr == 1 && isRgbBlack(cdd)) cpick.color.setChannel('hsv', 'v', 100);
if (sr != 2 && hasWhite) w = parseInt(gId('sliderW').value);
var col = cpick.color.rgb;
cdd.r = r = hasRGB ? col.r : w;
cdd.g = g = hasRGB ? col.g : w;
cdd.b = b = hasRGB ? col.b : w;
cdd.w = w;
setCSL(cd[csel]);
setCSL(cd);
var obj = {"seg": {"col": [[],[],[]]}};
obj.seg.col[csel] = [r, g, b, w];
requestJson(obj);
Expand Down
Loading
Loading