Adopted WLED-SR slider, color & palette control.
Added "freeze" toggle to a stopwatch icon.
This commit is contained in:
parent
044d830b64
commit
cc7d745ce6
153
wled00/FX.h
153
wled00/FX.h
@ -907,20 +907,147 @@ class WS2812FX {
|
||||
transitionProgress(uint8_t tNr);
|
||||
};
|
||||
|
||||
//10 names per line
|
||||
// WLEDSR: extensions
|
||||
// Technical notes
|
||||
// ===============
|
||||
// If an effect name is followed by an @, slider and color control is effective.
|
||||
// See setSliderAndColorControl in index.js for implementation
|
||||
// If not effective then:
|
||||
// - For AC effects (id<128) 2 sliders and 3 colors and the palette will be shown
|
||||
// - For SR effects (id>128) 5 sliders and 3 colors and the palette will be shown
|
||||
// If effective (@)
|
||||
// - a ; seperates slider controls (left) from color controls (middle) and palette control (right)
|
||||
// - if left, middle or right is empty no controls are shown
|
||||
// - a , seperates slider controls (max 5) or color controls (max 3). Palette has only one value
|
||||
// - a ! means that the default is used.
|
||||
// - For sliders: Effect speeds, Effect intensity, Custom 1, Custom 2, Custom 3
|
||||
// - For colors: Fx color, Background color, Custom
|
||||
// - For palette: prompt Color palette
|
||||
//
|
||||
// Note: If palette is on and no colors are specified 1,2 and 3 is shown in each color circle.
|
||||
// If a color is specified, the 1,2 or 3 is replaced by that specification.
|
||||
// Note: Effects can override default pattern behaviour
|
||||
// - FadeToBlack can override the background setting
|
||||
// - Defining SEGCOL(<i>) can override a specific palette using these values (e.g. Color Gradient)
|
||||
const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"Solid","Blink","Breathe","Wipe","Wipe Random","Random Colors","Sweep","Dynamic","Colorloop","Rainbow",
|
||||
"Scan","Scan Dual","Fade","Theater","Theater Rainbow","Running","Saw","Twinkle","Dissolve","Dissolve Rnd",
|
||||
"Sparkle","Sparkle Dark","Sparkle+","Strobe","Strobe Rainbow","Strobe Mega","Blink Rainbow","Android","Chase","Chase Random",
|
||||
"Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Aurora","Stream",
|
||||
"Scanner","Lighthouse","Fireworks","Rain","Tetrix","Fire Flicker","Gradient","Loading","Police","Police All",
|
||||
"Two Dots","Two Areas","Running Dual","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet",
|
||||
"Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise",
|
||||
"Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple",
|
||||
"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","Dancing Shadows","Washing Machine","Candy Cane","Blends","TV Simulator","Dynamic Smooth"
|
||||
"Solid",
|
||||
"Blink@;!;!",
|
||||
"Breathe@Speed;,!;!",
|
||||
"Wipe",
|
||||
"Wipe Random",
|
||||
"Random Colors",
|
||||
"Sweep",
|
||||
"Dynamic",
|
||||
"Colorloop",
|
||||
"Rainbow",
|
||||
"Scan@!,# of dots;,!,?;!",
|
||||
"Scan Dual@!,# of dots;,!,?;!",
|
||||
"Fade",
|
||||
"Theater",
|
||||
"Theater Rainbow",
|
||||
"Running",
|
||||
"Saw",
|
||||
"Twinkle",
|
||||
"Dissolve",
|
||||
"Dissolve Rnd",
|
||||
"Sparkle",
|
||||
"Sparkle Dark",
|
||||
"Sparkle+",
|
||||
"Strobe",
|
||||
"Strobe Rainbow",
|
||||
"Strobe Mega",
|
||||
"Blink Rainbow",
|
||||
"Android",
|
||||
"Chase",
|
||||
"Chase Random",
|
||||
"Chase Rainbow",
|
||||
"Chase Flash",
|
||||
"Chase Flash Rnd",
|
||||
"Rainbow Runner",
|
||||
"Colorful",
|
||||
"Traffic Light",
|
||||
"Sweep Random",
|
||||
"Running 2",
|
||||
"Aurora",
|
||||
"Stream",
|
||||
"Scanner",
|
||||
"Lighthouse",
|
||||
"Fireworks",
|
||||
"Rain",
|
||||
"Tetrix@Speed,Width;Fx,BG,;!",
|
||||
"Fire Flicker",
|
||||
"Gradient",
|
||||
"Loading",
|
||||
"Police",
|
||||
"Police All",
|
||||
"Two Dots",
|
||||
"Two Areas",
|
||||
"Running Dual",
|
||||
"Halloween",
|
||||
"Tri Chase",
|
||||
"Tri Wipe",
|
||||
"Tri Fade",
|
||||
"Lightning",
|
||||
"ICU",
|
||||
"Multi Comet",
|
||||
"Scanner Dual",
|
||||
"Stream 2",
|
||||
"Oscillate",
|
||||
"Pride 2015",
|
||||
"Juggle",
|
||||
"Palette",
|
||||
"Fire 2012",
|
||||
"Colorwaves",
|
||||
"Bpm",
|
||||
"Fill Noise",
|
||||
"Noise 1",
|
||||
"Noise 2",
|
||||
"Noise 3",
|
||||
"Noise 4",
|
||||
"Colortwinkles",
|
||||
"Lake",
|
||||
"Meteor",
|
||||
"Meteor Smooth",
|
||||
"Railway",
|
||||
"Ripple",
|
||||
"Twinklefox",
|
||||
"Twinklecat",
|
||||
"Halloween Eyes",
|
||||
"Solid Pattern",
|
||||
"Solid Pattern Tri",
|
||||
"Spots",
|
||||
"Spots Fade",
|
||||
"Glitter",
|
||||
"Candle",
|
||||
"Fireworks Starburst",
|
||||
"Fireworks 1D@Gravity,Firing side;;!",
|
||||
"Bouncing Balls",
|
||||
"Sinelon",
|
||||
"Sinelon Dual",
|
||||
"Sinelon Rainbow",
|
||||
"Popcorn",
|
||||
"Drip@Gravity,# of drips;!,!;!",
|
||||
"Plasma",
|
||||
"Percent",
|
||||
"Ripple Rainbow",
|
||||
"Heartbeat",
|
||||
"Pacifica",
|
||||
"Candle Multi",
|
||||
"Solid Glitter",
|
||||
"Sunrise",
|
||||
"Phased",
|
||||
"Twinkleup@Speed,Intensity,Min;,!;!",
|
||||
"Noise Pal",
|
||||
"Sine",
|
||||
"Phased Noise",
|
||||
"Flow",
|
||||
"Chunchun",
|
||||
"Dancing Shadows",
|
||||
"Washing Machine",
|
||||
"Candy Cane",
|
||||
"Blends",
|
||||
"TV Simulator",
|
||||
"Dynamic Smooth"
|
||||
])=====";
|
||||
|
||||
|
||||
|
@ -357,21 +357,25 @@ button {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#staytop, #staytop1 {
|
||||
#slider0, #slider1, #slider2, #slider3, #slider4 {
|
||||
background: var(--c-2);
|
||||
width: 310px;
|
||||
margin: auto;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
#staytop1 {
|
||||
#sliderLabel2, #sliderLabel3, #sliderLabel4,
|
||||
#slider2, #slider3, #slider4 {
|
||||
display: none;
|
||||
}
|
||||
/*
|
||||
#slider1 {
|
||||
top: 28px;
|
||||
}
|
||||
|
||||
#staytop2 {
|
||||
#fxFind {
|
||||
top: 58px;
|
||||
}
|
||||
|
||||
*/
|
||||
.first {
|
||||
margin-top: 10px;
|
||||
}
|
||||
@ -1078,18 +1082,20 @@ input[type=number]::-webkit-outer-spin-button {
|
||||
.lstI.sticky, .lstI.selected {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/*
|
||||
#fxlist .lstI.selected {
|
||||
top: 142px;
|
||||
}
|
||||
|
||||
*/
|
||||
#pallist .lstI.selected {
|
||||
top: 84px;
|
||||
}
|
||||
/* must be after .selected */
|
||||
/*
|
||||
#fxlist .lstI.sticky {
|
||||
top: 99px;
|
||||
}
|
||||
*/
|
||||
#pallist .lstI.sticky {
|
||||
top: 42px;
|
||||
}
|
||||
|
@ -52,21 +52,18 @@
|
||||
<input id="sliderR" class="noslide" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<!--output class="sliderbubble"></output-->
|
||||
</div><br>
|
||||
<div id="gwrap" class="il">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderG" class="noslide" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<!--output class="sliderbubble"></output-->
|
||||
</div><br>
|
||||
<div id="bwrap" class="il">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderB" class="noslide" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<!--output class="sliderbubble"></output-->
|
||||
</div><br>
|
||||
</div>
|
||||
<div id="wwrap">
|
||||
@ -75,7 +72,6 @@
|
||||
<input id="sliderW" class="noslide" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<!--output class="sliderbubble"></output-->
|
||||
</div>
|
||||
<div id="wbal">
|
||||
<p class="labels hd">White balance</p>
|
||||
@ -83,7 +79,6 @@
|
||||
<input id="sliderA" class="noslide" onchange="setBalance(this.value)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<!--output class="sliderbubble"></output-->
|
||||
</div>
|
||||
<div id="qcs-w">
|
||||
<div class="qcs" onclick="pC('#ff0000');" title="Red" style="background-color:#ff0000;"></div>
|
||||
@ -99,16 +94,17 @@
|
||||
<div class="qcs" onclick="pC('rnd');" title="Random" style="background:linear-gradient(to right, red, orange, yellow, green, blue, purple);transform: translateY(-11px);">R</div>
|
||||
</div>
|
||||
<div id="csl">
|
||||
<button id="csl-0" class="btn xxs" onclick="selectSlot(0);">1</button>
|
||||
<button id="csl-1" class="btn xxs" onclick="selectSlot(1);">2</button>
|
||||
<button id="csl-2" class="btn xxs" onclick="selectSlot(2);">3</button>
|
||||
<button id="csl0" class="btn xxs" onclick="selectSlot(0);">1</button>
|
||||
<button id="csl1" class="btn xxs" onclick="selectSlot(1);">2</button>
|
||||
<button id="csl2" class="btn xxs" onclick="selectSlot(2);">3</button>
|
||||
</div>
|
||||
<p class="labels h" id="cslLabel"></p>
|
||||
<div id="hexw">
|
||||
<input id="hexc" type="text" class="noslide" onkeydown="hexEnter(this)" autocomplete="off" maxlength="8" />
|
||||
<button id="hexcnf" class="btn btn-xs" onclick="fromHex();"><i class="icons btn-icon"></i></button>
|
||||
</div>
|
||||
<div id="palw" class="il">
|
||||
<p class="labels"><i class="icons sel-icon" onclick="tglHex()"></i> Color palette</p>
|
||||
<p class="labels" id="pall"><i class="icons sel-icon" onclick="tglHex()"></i> Color palette</p>
|
||||
<div class="staytop fnd">
|
||||
<input type="text" class="fnd" placeholder="Search" oninput="search(this,'pallist')" onfocus="search(this,'pallist')" />
|
||||
<i class="icons clear-icon" onclick="clean(this)"></i>
|
||||
@ -140,17 +136,17 @@
|
||||
</div>
|
||||
|
||||
<div id="Effects" class="tabcontent">
|
||||
<p class="labels">Effect speed</p>
|
||||
<div class="staytop" id="staytop">
|
||||
<i class="icons slider-icon"></i>
|
||||
<p class="labels" id="sliderLabel0">Effect speed</p>
|
||||
<div class="staytop" id="slider0">
|
||||
<i class="icons slider-icon" onclick="tglFreeze()"></i>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderSpeed" class="noslide" onchange="setSpeed()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<output class="sliderbubble"></output>
|
||||
</div>
|
||||
<p class="labels">Effect intensity</p>
|
||||
<div class="staytop" id="staytop1">
|
||||
<p class="labels" id="sliderLabel1">Effect intensity</p>
|
||||
<div class="staytop" id="slider1">
|
||||
<i class="icons slider-icon" onclick="tglLabels()"></i>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderIntensity" class="noslide" onchange="setIntensity()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
|
||||
@ -158,9 +154,36 @@
|
||||
</div>
|
||||
<output class="sliderbubble"></output>
|
||||
</div>
|
||||
<p class="labels" id="sliderLabel2">Custom 1</p>
|
||||
<div class="staytop" id="slider2">
|
||||
<i class="icons slider-icon"></i>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderC1" class="noslide" onchange="setFFT1()" oninput="updateTrail(this)" max="255" min="0" type="range" value="6" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<output class="sliderbubble"></output>
|
||||
</div>
|
||||
<p class="labels" id="sliderLabel3">Custom 2</p>
|
||||
<div class="staytop" id="slider3">
|
||||
<i class="icons slider-icon"></i>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderC2" class="noslide" onchange="setFFT2()" oninput="updateTrail(this)" max="255" min="0" type="range" value="6" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<output class="sliderbubble"></output>
|
||||
</div>
|
||||
<p class="labels" id="sliderLabel4">Custom 3</p>
|
||||
<div class="staytop" id="slider4">
|
||||
<i class="icons slider-icon"></i>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderC3" class="noslide" onchange="setFFT3()" oninput="updateTrail(this)" max="255" min="0" type="range" value="6" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<output class="sliderbubble"></output>
|
||||
</div>
|
||||
<div class="il">
|
||||
<p class="labels">Effect mode</p>
|
||||
<div class="staytop fnd" id="staytop2">
|
||||
<p class="labels" id="modeLabel">Effect mode</p>
|
||||
<div class="staytop fnd" id="fxFind">
|
||||
<input type="text" class="fnd" placeholder="Search" oninput="search(this,'fxlist')" onfocus="search(this,'fxlist')" />
|
||||
<i class="icons clear-icon" onclick="clean(this);"></i>
|
||||
<i class="icons search-icon"></i>
|
||||
|
@ -10,6 +10,7 @@ var nlDur = 60, nlTar = 0;
|
||||
var nlMode = false;
|
||||
var selectedFx = 0;
|
||||
var selectedPal = 0;
|
||||
var sliderControl = ""; //WLEDSR: used by togglePcMode
|
||||
var csel = 0;
|
||||
var currentPreset = -1;
|
||||
var lastUpdate = 0;
|
||||
@ -731,66 +732,6 @@ function populateSegments(s)
|
||||
gId('rsbtn').style.display = (segCount > 1) ? "inline":"none";
|
||||
}
|
||||
|
||||
function btype(b)
|
||||
{
|
||||
switch (b) {
|
||||
case 32: return "ESP32";
|
||||
case 82: return "ESP8266";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
function bname(o)
|
||||
{
|
||||
if (o.name=="WLED") return o.ip;
|
||||
return o.name;
|
||||
}
|
||||
|
||||
function populateNodes(i,n)
|
||||
{
|
||||
var cn="";
|
||||
var urows="";
|
||||
var nnodes = 0;
|
||||
if (n.nodes) {
|
||||
n.nodes.sort((a,b) => (a.name).localeCompare(b.name));
|
||||
for (var x=0;x<n.nodes.length;x++) {
|
||||
var o = n.nodes[x];
|
||||
if (o.name) {
|
||||
var url = `<button class="btn" title="${o.ip}" onclick="location.assign('http://${o.ip}');">${bname(o)}</button>`;
|
||||
urows += inforow(url,`${btype(o.type)}<br><i>${o.vid==0?"N/A":o.vid}</i>`);
|
||||
nnodes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i.ndc < 0) cn += `Instance List is disabled.`;
|
||||
else if (nnodes == 0) cn += `No other instances found.`;
|
||||
cn += `<table>
|
||||
${inforow("Current instance:",i.name)}
|
||||
${urows}
|
||||
</table>`;
|
||||
gId('kn').innerHTML = cn;
|
||||
}
|
||||
|
||||
function loadNodes()
|
||||
{
|
||||
var url = (loc?`http://${locip}`:'') + '/json/nodes';
|
||||
fetch(url, {
|
||||
method: 'get'
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) showToast('Could not load Node list!', true);
|
||||
return res.json();
|
||||
})
|
||||
.then(json => {
|
||||
clearErrorToast();
|
||||
populateNodes(lastinfo, json);
|
||||
})
|
||||
.catch(function (error) {
|
||||
showToast(error, true);
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function populateEffects()
|
||||
{
|
||||
var effects = eJson;
|
||||
@ -802,16 +743,27 @@ function populateEffects()
|
||||
|
||||
effects.unshift({
|
||||
"id": 0,
|
||||
"name": "Solid"
|
||||
"name": "Solid@;!;"
|
||||
});
|
||||
|
||||
for (let i = 0; i < effects.length; i++) {
|
||||
html += generateListItemHtml(
|
||||
'fx',
|
||||
effects[i].id,
|
||||
effects[i].name,
|
||||
'setX'
|
||||
);
|
||||
// WLEDSR: add slider and color control to setX (used by requestjson)
|
||||
if (effects[i].name.indexOf("Reserved") < 0) {
|
||||
var posAt = effects[i].name.indexOf("@");
|
||||
var extra = '';
|
||||
if (posAt > 0)
|
||||
extra = effects[i].name.substr(posAt);
|
||||
else
|
||||
posAt = 999;
|
||||
html += generateListItemHtml(
|
||||
'fx',
|
||||
effects[i].id,
|
||||
effects[i].name.substr(0,posAt),
|
||||
'setX',
|
||||
'','',
|
||||
extra
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
gId('fxlist').innerHTML=html;
|
||||
@ -894,15 +846,15 @@ function genPalPrevCss(id)
|
||||
} else {
|
||||
if (selColors) {
|
||||
let e = element[1] - 1;
|
||||
if (Array.isArray(selColors[e])) {
|
||||
//if (Array.isArray(selColors[e])) {
|
||||
r = selColors[e][0];
|
||||
g = selColors[e][1];
|
||||
b = selColors[e][2];
|
||||
} else {
|
||||
r = (selColors[e]>>16) & 0xFF;
|
||||
g = (selColors[e]>> 8) & 0xFF;
|
||||
b = (selColors[e] ) & 0xFF;
|
||||
}
|
||||
//} else {
|
||||
// r = (selColors[e]>>16) & 0xFF;
|
||||
// g = (selColors[e]>> 8) & 0xFF;
|
||||
// b = (selColors[e] ) & 0xFF;
|
||||
//}
|
||||
}
|
||||
}
|
||||
if (index === false) {
|
||||
@ -915,9 +867,9 @@ function genPalPrevCss(id)
|
||||
return `background: linear-gradient(to right,${gradient.join()});`;
|
||||
}
|
||||
|
||||
function generateListItemHtml(listName, id, name, clickAction, extraHtml = '')
|
||||
function generateListItemHtml(listName, id, name, clickAction, extraHtml = '', extraClass = '', extraPar = '')
|
||||
{
|
||||
return `<div class="lstI${id==0?' sticky':''}" data-id="${id}" onClick="${clickAction}(${id})">
|
||||
return `<div class="lstI${id==0?' sticky':''} ${extraClass}" data-id="${id}" onClick="${clickAction}(${id},'${extraPar}')">
|
||||
<label class="radio schkl" onclick="event.preventDefault()">
|
||||
|
||||
<input type="radio" value="${id}" name="${listName}">
|
||||
@ -932,6 +884,66 @@ function generateListItemHtml(listName, id, name, clickAction, extraHtml = '')
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function btype(b)
|
||||
{
|
||||
switch (b) {
|
||||
case 32: return "ESP32";
|
||||
case 82: return "ESP8266";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
function bname(o)
|
||||
{
|
||||
if (o.name=="WLED") return o.ip;
|
||||
return o.name;
|
||||
}
|
||||
|
||||
function populateNodes(i,n)
|
||||
{
|
||||
var cn="";
|
||||
var urows="";
|
||||
var nnodes = 0;
|
||||
if (n.nodes) {
|
||||
n.nodes.sort((a,b) => (a.name).localeCompare(b.name));
|
||||
for (var x=0;x<n.nodes.length;x++) {
|
||||
var o = n.nodes[x];
|
||||
if (o.name) {
|
||||
var url = `<button class="btn" title="${o.ip}" onclick="location.assign('http://${o.ip}');">${bname(o)}</button>`;
|
||||
urows += inforow(url,`${btype(o.type)}<br><i>${o.vid==0?"N/A":o.vid}</i>`);
|
||||
nnodes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i.ndc < 0) cn += `Instance List is disabled.`;
|
||||
else if (nnodes == 0) cn += `No other instances found.`;
|
||||
cn += `<table>
|
||||
${inforow("Current instance:",i.name)}
|
||||
${urows}
|
||||
</table>`;
|
||||
gId('kn').innerHTML = cn;
|
||||
}
|
||||
|
||||
function loadNodes()
|
||||
{
|
||||
var url = (loc?`http://${locip}`:'') + '/json/nodes';
|
||||
fetch(url, {
|
||||
method: 'get'
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) showToast('Could not load Node list!', true);
|
||||
return res.json();
|
||||
})
|
||||
.then(json => {
|
||||
clearErrorToast();
|
||||
populateNodes(lastinfo, json);
|
||||
})
|
||||
.catch(function (error) {
|
||||
showToast(error, true);
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function updateTrail(e)
|
||||
{
|
||||
if (e==null) return;
|
||||
@ -1014,19 +1026,14 @@ function updateUI()
|
||||
updateTrail(gId('sliderBri'));
|
||||
updateTrail(gId('sliderSpeed'));
|
||||
updateTrail(gId('sliderIntensity'));
|
||||
|
||||
updateTrail(gId('sliderC1'));
|
||||
updateTrail(gId('sliderC2'));
|
||||
updateTrail(gId('sliderC3'));
|
||||
|
||||
gId('wwrap').style.display = (isRgbw) ? "block":"none";
|
||||
gId("wbal").style.display = (lastinfo.leds.cct) ? "block":"none";
|
||||
|
||||
if (selectedFx===0) {
|
||||
gId("csl-1").style.display = "none";
|
||||
gId("csl-2").style.display = "none";
|
||||
gId("palw").style.display = "none";
|
||||
} else {
|
||||
gId("csl-1").style.display = "inline-block";
|
||||
gId("csl-2").style.display = "inline-block";
|
||||
gId("palw").style.display = "inline-block";
|
||||
}
|
||||
|
||||
updatePA();
|
||||
updateHex();
|
||||
updateRgb();
|
||||
@ -1055,7 +1062,20 @@ function updateSelectedFx()
|
||||
if (selElement) selElement.classList.remove('selected');
|
||||
|
||||
var selectedEffect = parent.querySelector(`.lstI[data-id="${selectedFx}"]`);
|
||||
if (selectedEffect) selectedEffect.classList.add('selected');
|
||||
if (selectedEffect) {
|
||||
selectedEffect.classList.add('selected');
|
||||
|
||||
// WLEDSR: extract the Slider and color control string from the HTML element and set it.
|
||||
sliderControl = selectedEffect.outerHTML.replace(/&/g, "&");
|
||||
var posAt = sliderControl.indexOf("@");
|
||||
if (posAt > 0) {
|
||||
sliderControl = sliderControl.substring(posAt);
|
||||
var posAt = sliderControl.indexOf(')"');
|
||||
sliderControl = sliderControl.substring(0,posAt-1);
|
||||
} else
|
||||
sliderControl = "";
|
||||
setSliderAndColorControl(selectedFx, sliderControl);
|
||||
}
|
||||
}
|
||||
|
||||
function displayRover(i,s)
|
||||
@ -1124,7 +1144,7 @@ function readState(s,command=false)
|
||||
else currentPreset = s.pl;
|
||||
|
||||
tr = s.transition;
|
||||
d.gId('tt').value = tr/10;
|
||||
gId('tt').value = tr/10;
|
||||
|
||||
var selc=0; var ind=0;
|
||||
populateSegments(s);
|
||||
@ -1144,18 +1164,18 @@ function readState(s,command=false)
|
||||
for (let e = cd.length-1; e >= 0; e--)
|
||||
{
|
||||
var r,g,b,w;
|
||||
if (Array.isArray(i.col[e])) {
|
||||
//if (Array.isArray(i.col[e])) {
|
||||
r = i.col[e][0];
|
||||
g = i.col[e][1];
|
||||
b = i.col[e][2];
|
||||
if (isRgbw) w = i.col[e][3];
|
||||
} else {
|
||||
// unsigned long RGBW (@blazoncek v2 experimental API implementation, obsolete & will be removed)
|
||||
r = (i.col[e]>>16) & 0xFF;
|
||||
g = (i.col[e]>> 8) & 0xFF;
|
||||
b = (i.col[e] ) & 0xFF;
|
||||
if (isRgbw) w = (i.col[e] >> 24) & 0xFF;
|
||||
}
|
||||
//} else {
|
||||
// // unsigned long RGBW (@blazoncek v2 experimental API implementation, obsolete & will be removed)
|
||||
// r = (i.col[e]>>16) & 0xFF;
|
||||
// g = (i.col[e]>> 8) & 0xFF;
|
||||
// b = (i.col[e] ) & 0xFF;
|
||||
// if (isRgbw) w = (i.col[e] >> 24) & 0xFF;
|
||||
//}
|
||||
cd[e].style.backgroundColor = "rgb(" + r + "," + g + "," + b + ")";
|
||||
if (isRgbw) whites[e] = parseInt(w);
|
||||
}
|
||||
@ -1166,6 +1186,10 @@ function readState(s,command=false)
|
||||
gId('sliderSpeed').value = i.sx;
|
||||
gId('sliderIntensity').value = i.ix;
|
||||
|
||||
gId('sliderC1').value = i.f1x ? i.f1x : 0;
|
||||
gId('sliderC2').value = i.f2x ? i.f2x : 0;
|
||||
gId('sliderC3').value = i.f3x ? i.f3x : 0;
|
||||
|
||||
if (s.error && s.error != 0) {
|
||||
var errstr = "";
|
||||
switch (s.error) {
|
||||
@ -1194,6 +1218,99 @@ function readState(s,command=false)
|
||||
updateUI();
|
||||
}
|
||||
|
||||
// WLEDSR: control HTML elements for Slider and Color Control
|
||||
function setSliderAndColorControl(idx, extra)
|
||||
{
|
||||
var topPosition = 0;
|
||||
var controlDefined = (extra.substr(0,1) == "@")?true:false;
|
||||
extra = extra.substr(1);
|
||||
var extras = (extra == '')?[]:extra.split(";");
|
||||
var slOnOff = (extras.length==0 || extras[0]=='')?[]:extras[0].split(",");
|
||||
var coOnOff = (extras.length<2 || extras[1]=='')?[]:extras[1].split(",");
|
||||
var paOnOff = (extras.length<3 || extras[2]=='')?[]:extras[2].split(",");
|
||||
|
||||
// set html slider items on/off
|
||||
var nSliders = (gId("Effects").children.length - 1) / 2; // p (label) & div for each slider + FX list
|
||||
for (let i=0; i<nSliders; i++) {
|
||||
var slider = gId("slider" + i);
|
||||
var label = gId("sliderLabel" + i);
|
||||
// if (not controlDefined and for AC speed or intensity and for SR alle sliders) or slider has a value
|
||||
if ((!controlDefined && i < ((idx<128)?2:nSliders)) || (slOnOff.length>i && slOnOff[i] != "")) {
|
||||
label.style.display = "block";
|
||||
if (slOnOff.length>i && slOnOff[i]!="!") label.innerHTML = slOnOff[i];
|
||||
else if (i==0) label.innerHTML = "Effect speed";
|
||||
else if (i==1) label.innerHTML = "Effect intensity";
|
||||
else label.innerHTML = "Custom" + (i-1);
|
||||
label.style.top = "auto";
|
||||
slider.style.display = "block";
|
||||
slider.style.top = topPosition + "px";
|
||||
topPosition += 28; // increase top position for the next control
|
||||
slider.setAttribute('title',label.innerHTML);
|
||||
} else {
|
||||
// disable label and slider
|
||||
slider.style.display = "none";
|
||||
label.style.display = "none";
|
||||
}
|
||||
}
|
||||
if (topPosition>0) topPosition += 2;
|
||||
|
||||
// set top position of the effect list
|
||||
gId("fxFind").style.top = topPosition + "px";
|
||||
topPosition += 42;
|
||||
var fxList = gId("fxlist");
|
||||
for (var i=0; i<fxList.children.length; i++) fxList.children[i].style.top = null; // remove top
|
||||
var selected = fxList.querySelector('.selected');
|
||||
var sticky = fxList.querySelector('.sticky');
|
||||
if (sticky) {
|
||||
sticky.style.top = topPosition + "px";
|
||||
topPosition += 42;
|
||||
}
|
||||
if (selected && !selected.style.top) { // is the sticky element also selected one?
|
||||
selected.style.top = topPosition + "px";
|
||||
}
|
||||
|
||||
// set html color items on/off
|
||||
var cslLabel = '';
|
||||
var sep = '';
|
||||
for (let i=0; i<gId("csl").children.length; i++) {
|
||||
var btn = gId("csl" + i);
|
||||
// if no controlDefined or coOnOff has a value
|
||||
if (coOnOff.length>i && coOnOff[i] != "") {
|
||||
btn.style.display = "inline";
|
||||
if (coOnOff.length>i && coOnOff[i] != "!") {
|
||||
var abbreviation = coOnOff[i].substr(0,2);
|
||||
btn.innerHTML = abbreviation;
|
||||
if (abbreviation != coOnOff[i]) {
|
||||
cslLabel += sep + abbreviation + '=' + coOnOff[i];
|
||||
sep = ', ';
|
||||
}
|
||||
}
|
||||
else if (i==0) btn.innerHTML = "Fx";
|
||||
else if (i==1) btn.innerHTML = "Bg";
|
||||
else btn.innerHTML = "Cs";
|
||||
} else if (!controlDefined || paOnOff.length>0) { // if no controls or palette then all buttons should be shown for color 1..3 palettes
|
||||
btn.style.display = "inline";
|
||||
btn.innerHTML = `${i+1}`;
|
||||
} else {
|
||||
btn.style.display = "none";
|
||||
}
|
||||
}
|
||||
gId("cslLabel").innerHTML = cslLabel;
|
||||
|
||||
// set palette on/off
|
||||
var palw = gId("palw"); // wrapper
|
||||
var pall = gId("pall"); // list
|
||||
// if not controlDefined or palette has a value
|
||||
if ((!controlDefined) || (paOnOff.length>0 && paOnOff[0]!="")) {
|
||||
palw.style.display = "inline-block";
|
||||
if (paOnOff.length>0 && paOnOff[0] != "!") pall.innerHTML = paOnOff[0];
|
||||
else pall.innerHTML = '<i class="icons sel-icon" onclick="tglHex()"></i> Color palette';
|
||||
} else {
|
||||
// disable label and slider
|
||||
palw.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
var jsonTimeout;
|
||||
var reqsLegal = false;
|
||||
|
||||
@ -1211,7 +1328,7 @@ function requestJson(command=null)
|
||||
command.v = true; // force complete /json/si API response
|
||||
command.time = Math.floor(Date.now() / 1000);
|
||||
|
||||
var t = d.gId('tt');
|
||||
var t = gId('tt');
|
||||
if (t.validity.valid && command.transition==null) {
|
||||
var tn = parseInt(t.value*10);
|
||||
if (tn != tr) command.transition = tn;
|
||||
@ -1641,6 +1758,13 @@ function setSegBri(s)
|
||||
requestJson(obj);
|
||||
}
|
||||
|
||||
function tglFreeze(s=null)
|
||||
{
|
||||
var obj = {"seg": {"frz": "t"}}; // toggle
|
||||
if (s!==null) obj.id = s;
|
||||
requestJson(obj);
|
||||
}
|
||||
|
||||
function setX(ind = null)
|
||||
{
|
||||
if (ind === null) {
|
||||
|
4451
wled00/html_ui.h
4451
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -73,7 +73,10 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
bool on = elem["on"] | seg.getOption(SEG_OPTION_ON);
|
||||
if (elem["on"].is<const char*>() && elem["on"].as<const char*>()[0] == 't') on = !on;
|
||||
seg.setOption(SEG_OPTION_ON, on, id);
|
||||
|
||||
bool frz = elem["frz"] | seg.getOption(SEG_OPTION_FREEZE);
|
||||
if (elem["frz"].is<const char*>() && elem["frz"].as<const char*>()[0] == 't') frz = !seg.getOption(SEG_OPTION_FREEZE);
|
||||
seg.setOption(SEG_OPTION_FREEZE, frz, id);
|
||||
|
||||
seg.cct = elem["cct"] | seg.cct;
|
||||
|
||||
JsonArray colarr = elem["col"];
|
||||
@ -133,7 +136,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
|
||||
//if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal);
|
||||
seg.setOption(SEG_OPTION_SELECTED, elem[F("sel")] | seg.getOption(SEG_OPTION_SELECTED));
|
||||
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
|
||||
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
|
||||
seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR ));
|
||||
|
||||
//temporary, strip object gets updated via colorUpdated()
|
||||
@ -201,7 +204,8 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
}
|
||||
strip.setPixelSegment(255);
|
||||
strip.trigger();
|
||||
} else { //return to regular effect
|
||||
// this is now handled using the "frz" toggle.
|
||||
} else if (!elem["frz"] && iarr.isNull()) { //return to regular effect
|
||||
seg.setOption(SEG_OPTION_FREEZE, false);
|
||||
}
|
||||
return; // seg.differs(prev);
|
||||
@ -244,13 +248,13 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||
tr = root[F("tb")] | -1;
|
||||
if (tr >= 0) strip.timebase = ((uint32_t)tr) - millis();
|
||||
|
||||
JsonObject nl = root["nl"];
|
||||
JsonObject nl = root["nl"];
|
||||
nightlightActive = nl["on"] | nightlightActive;
|
||||
nightlightDelayMins = nl[F("dur")] | nightlightDelayMins;
|
||||
nightlightMode = nl[F("mode")] | nightlightMode;
|
||||
nightlightTargetBri = nl[F("tbri")] | nightlightTargetBri;
|
||||
|
||||
JsonObject udpn = root["udpn"];
|
||||
JsonObject udpn = root["udpn"];
|
||||
notifyDirect = udpn["send"] | notifyDirect;
|
||||
receiveNotifications = udpn["recv"] | receiveNotifications;
|
||||
if ((bool)udpn[F("nn")]) callMode = CALL_MODE_NO_NOTIFY; //send no notification just for this request
|
||||
@ -376,6 +380,7 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
|
||||
root[F("spc")] = seg.spacing;
|
||||
root[F("of")] = seg.offset;
|
||||
root["on"] = seg.getOption(SEG_OPTION_ON);
|
||||
root["frz"] = seg.getOption(SEG_OPTION_FREEZE);
|
||||
byte segbri = seg.opacity;
|
||||
root["bri"] = (segbri) ? segbri : 255;
|
||||
root["cct"] = seg.cct;
|
||||
@ -791,6 +796,37 @@ void serializeNodes(JsonObject root)
|
||||
}
|
||||
}
|
||||
|
||||
void serializeSRNames(JsonVariant arr, const char *qstring) {
|
||||
String lineBuffer;
|
||||
bool insideQuotes = false;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(qstring); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(qstring + i);
|
||||
if (singleJsonSymbol == '\0') break;
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
break;
|
||||
case ']':
|
||||
case ',':
|
||||
if (lineBuffer.length() > 0) {
|
||||
uint8_t endPos = lineBuffer.indexOf('@');
|
||||
if (endPos>0) arr.add(lineBuffer.substring(0,endPos));
|
||||
else arr.add(lineBuffer);
|
||||
lineBuffer.clear();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!insideQuotes) break;
|
||||
lineBuffer += singleJsonSymbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void serveJson(AsyncWebServerRequest* request)
|
||||
{
|
||||
byte subJson = 0;
|
||||
@ -805,6 +841,7 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
return;
|
||||
}
|
||||
else if (url.indexOf(F("eff")) > 0) {
|
||||
// this is going to serve raw effect names which will include WLED-SR extensions in names
|
||||
request->send_P(200, "application/json", JSON_mode_names);
|
||||
return;
|
||||
}
|
||||
@ -840,7 +877,9 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
serializeInfo(info);
|
||||
if (subJson != 3)
|
||||
{
|
||||
doc[F("effects")] = serialized((const __FlashStringHelper*)JSON_mode_names);
|
||||
//doc[F("effects")] = serialized((const __FlashStringHelper*)JSON_mode_names);
|
||||
JsonArray effects = doc.createNestedArray(F("effects"));
|
||||
serializeSRNames(effects, JSON_mode_names); // remove WLED-SR extensions from effect names
|
||||
doc[F("palettes")] = serialized((const __FlashStringHelper*)JSON_palette_names);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2110291
|
||||
#define VERSION 2110311
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
|
Loading…
Reference in New Issue
Block a user