POC: Implemented segment groups (4).
Sacrificed 1 bit on sound simulation and 1D to 2D mapping each.
This commit is contained in:
parent
af44730418
commit
558b22c36a
@ -349,8 +349,9 @@ typedef struct Segment {
|
||||
bool reverse_y : 1; // 7 : reversed Y (2D)
|
||||
bool mirror_y : 1; // 8 : mirrored Y (2D)
|
||||
bool transpose : 1; // 9 : transposed (2D, swapped X & Y)
|
||||
uint8_t map1D2D : 3; // 10-12 : mapping for 1D effect on 2D (0-use as strip, 1-expand vertically, 2-circular/arc, 3-rectangular/corner, ...)
|
||||
uint8_t soundSim : 3; // 13-15 : 0-7 sound simulation types
|
||||
uint8_t map1D2D : 2; // 10-11 : mapping for 1D effect on 2D (0-use as strip, 1-expand vertically, 2-circular/arc, 3-rectangular/corner, ...)
|
||||
uint8_t soundSim : 2; // 12-13 : 0-3 sound simulation types
|
||||
uint8_t group : 2; // 14-15 : 0-3 UI segment groups
|
||||
};
|
||||
};
|
||||
uint8_t grouping, spacing;
|
||||
|
@ -472,8 +472,8 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
|
||||
sOpt = extractModeDefaults(fx, "o1"); check1 = (sOpt >= 0) ? (bool)sOpt : false;
|
||||
sOpt = extractModeDefaults(fx, "o2"); check2 = (sOpt >= 0) ? (bool)sOpt : false;
|
||||
sOpt = extractModeDefaults(fx, "o3"); check3 = (sOpt >= 0) ? (bool)sOpt : false;
|
||||
sOpt = extractModeDefaults(fx, "m12"); if (sOpt >= 0) map1D2D = constrain(sOpt, 0, 7);
|
||||
sOpt = extractModeDefaults(fx, "si"); if (sOpt >= 0) soundSim = constrain(sOpt, 0, 7);
|
||||
sOpt = extractModeDefaults(fx, "m12"); if (sOpt >= 0) map1D2D = constrain(sOpt, 0, 3);
|
||||
sOpt = extractModeDefaults(fx, "si"); if (sOpt >= 0) soundSim = constrain(sOpt, 0, 3);
|
||||
sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) reverse = (bool)sOpt;
|
||||
sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) mirror = (bool)sOpt; // NOTE: setting this option is a risky business
|
||||
sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) reverse_y = (bool)sOpt;
|
||||
|
@ -178,18 +178,49 @@ button {
|
||||
}
|
||||
|
||||
.e-icon {
|
||||
transform: translateY(3px);
|
||||
/*transform: translateY(3px);*/
|
||||
}
|
||||
|
||||
.sel-icon {
|
||||
transform: translateX(3px);
|
||||
}
|
||||
|
||||
.e-icon, .sel-icon, .slider-icon {
|
||||
.e-icon, .g-icon, .sel-icon, .slider-icon {
|
||||
cursor: pointer;
|
||||
color: var(--c-d);
|
||||
}
|
||||
|
||||
.g-icon {
|
||||
font-style: normal;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
|
||||
/* pop-up container */
|
||||
.pop {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/* pop-up content */
|
||||
.pop-c {
|
||||
position: absolute;
|
||||
background-color: var(--c-5);
|
||||
border: 1px solid var(--c-e);
|
||||
border-radius: 16px;
|
||||
z-index: 1;
|
||||
top: 3px;
|
||||
left: -164px;
|
||||
padding: 4px 8px 2px;
|
||||
font-size: 24px;
|
||||
}
|
||||
.pop-c span {
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
@ -201,7 +232,6 @@ button {
|
||||
|
||||
.clear-icon {
|
||||
position: absolute;
|
||||
display: none;
|
||||
top: 8px;
|
||||
right: 9px;
|
||||
cursor: pointer;
|
||||
@ -229,14 +259,12 @@ button {
|
||||
|
||||
#liveview {
|
||||
height: 4px;
|
||||
display: none;
|
||||
width: 100%;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
#liveview2D {
|
||||
height: 90%;
|
||||
display: none;
|
||||
width: 90%;
|
||||
border: 0px;
|
||||
position: absolute;
|
||||
@ -467,13 +495,6 @@ button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#pql, .edit-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
.fade {
|
||||
visibility: hidden; /* hide it */
|
||||
opacity: 0; /* make it transparent */
|
||||
@ -551,7 +572,6 @@ button {
|
||||
position: fixed;
|
||||
top: calc(var(--th) + 5px);
|
||||
left: 1px;
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@ -651,7 +671,9 @@ img {
|
||||
#wbal .sliderdisplay { background: linear-gradient(90deg, #ff8f1f 0%, #fff 50%, #cbdbff); }
|
||||
|
||||
/* wrapper divs hidden by default */
|
||||
#rgbwrap, #swrap, #hwrap, #kwrap, #wwrap, #wbal, #qcs-w, #hexw {
|
||||
#liveview, #liveview2D, #roverstar, #pql
|
||||
#rgbwrap, #swrap, #hwrap, #kwrap, #wwrap, #wbal, #qcs-w, #hexw,
|
||||
.clear-icon, .edit-icon, .ptxt {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -985,7 +1007,6 @@ textarea {
|
||||
|
||||
.ptxt {
|
||||
margin: -1px 4px 8px !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.stxt {
|
||||
@ -1088,18 +1109,14 @@ textarea {
|
||||
}
|
||||
|
||||
.frz {
|
||||
left: 32px;
|
||||
left: 10px;
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
top: 8px;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
/*padding: 8px;*/
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.expanded .frz {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* radiobuttons and checkmarks */
|
||||
.check, .radio {
|
||||
display: block;
|
||||
@ -1412,13 +1429,13 @@ TD .checkmark, TD .radiomark {
|
||||
|
||||
.check input:checked ~ .checkmark:after,
|
||||
.radio input:checked ~ .radiomark:after,
|
||||
.show,
|
||||
.show, .g-icon,
|
||||
.expanded .edit-icon,
|
||||
.expanded .segin, .expanded .presin, .expanded .sbs,
|
||||
.expanded {
|
||||
display: inline-block !important;
|
||||
}
|
||||
.expanded .segin.hide, .expanded .presin.hide, .expanded .sbs.hide {
|
||||
.hide, .expanded .segin.hide, .expanded .presin.hide, .expanded .sbs.hide, .expanded .frz, .expanded .g-icon {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
@ -697,6 +697,13 @@ function populateSegments(s)
|
||||
let sg = gId(`seg${i}`);
|
||||
let exp = sg ? (sg.classList.contains('expanded') || (i===0 && cfg.comp.segexp)) : false;
|
||||
|
||||
let cG = "var(--c-b)";
|
||||
switch (inst.group) {
|
||||
case 1: cG = "var(--c-r)"; break;
|
||||
case 2: cG = "var(--c-g)"; break;
|
||||
case 3: cG = "var(--c-b)"; break;
|
||||
}
|
||||
|
||||
let segp = `<div id="segp${i}" class="sbs">
|
||||
<i class="icons e-icon pwr ${inst.on ? "act":""}" id="seg${i}pwr" onclick="setSegPwr(${i})"></i>
|
||||
<div class="sliderwrap il">
|
||||
@ -731,15 +738,19 @@ function populateSegments(s)
|
||||
<option value="3" ${inst.si==3?' selected':''}>U14_3</option>
|
||||
</select></div>
|
||||
</div>`;
|
||||
cn += `<div class="seg lstI ${i==s.mainseg ? 'selected' : ''} ${exp ? "expanded":""}" id="seg${i}">
|
||||
cn += `<div class="seg lstI ${i==s.mainseg ? 'selected' : ''} ${exp ? "expanded":""}" id="seg${i}" data-group="${inst.group?inst.group:0}">
|
||||
<label class="check schkl">
|
||||
<input type="checkbox" id="seg${i}sel" onchange="selSeg(${i})" ${inst.sel ? "checked":""}>
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<i class="icons e-icon frz" id="seg${i}frz" onclick="event.preventDefault();tglFreeze(${i});">&#x${inst.frz ? (li.live && li.liveseg==i?'e410':'e0e8') : 'e325'};</i>
|
||||
<div class="segname" onclick="selSegEx(${i})">
|
||||
<i class="icons e-icon frz" id="seg${i}frz" onclick="event.preventDefault();tglFreeze(${i});">&#x${inst.frz ? (li.live && li.liveseg==i?'e410':'e0e8') : 'e325'};</i>
|
||||
${inst.n ? inst.n : "Segment "+i}
|
||||
<i class="icons edit-icon flr" id="seg${i}nedit" onclick="tglSegn(${i})"></i>
|
||||
<div class="pop" onclick="event.preventDefault();event.stopPropagation();">
|
||||
<i class="icons g-icon" style="color:${cG};" onclick="this.nextElementSibling.classList.toggle('hide');">ɸ${String.fromCharCode(inst.group+"A".charCodeAt(0))};</i>
|
||||
<div class="pop-c hide"><span style="color:var(--c-b);" onclick="setGrp(${i},0);">➊</span><span style="color:var(--c-r);" onclick="setGrp(${i},1);">➋</span><span style="color:var(--c-g);" onclick="setGrp(${i},2);">➌</span><span style="color:var(--c-l);" onclick="setGrp(${i},3);">➍</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<i class="icons e-icon flr" id="sege${i}" onclick="expand(${i})"></i>
|
||||
${cfg.comp.segpwr?segp:''}
|
||||
@ -1750,7 +1761,11 @@ function resetUtil(off=false)
|
||||
{
|
||||
gId('segutil').innerHTML = `<div class="seg btn btn-s ${off?'off':''}" style="border-radius:24px;padding:0;">`
|
||||
+ '<label class="check schkl"><input type="checkbox" id="selall" onchange="selSegAll(this)"><span class="checkmark"></span></label>'
|
||||
+ `<div class="segname" ${off?'':'onclick="makeSeg()"'}><i class="icons btn-icon"></i>Add segment</div></div>`;
|
||||
+ `<div class="segname" ${off?'':'onclick="makeSeg()"'}><i class="icons btn-icon"></i>Add segment</div>`
|
||||
+ '<div class="pop" onclick="event.stopPropagation();">'
|
||||
+ `<i class="icons g-icon" style="color:var(--c-0);" onclick="this.nextElementSibling.classList.toggle('hide');">⎋</i>`
|
||||
+ '<div class="pop-c hide"><span style="color:var(--c-b);" onclick="selGrp(0);">➊</span><span style="color:var(--c-r);" onclick="selGrp(1);">➋</span><span style="color:var(--c-g);" onclick="selGrp(2);">➌</span><span style="color:var(--c-l);" onclick="selGrp(3);">➍</span></div>'
|
||||
+ '</div></div>';
|
||||
}
|
||||
|
||||
function makePlSel(el, incPl=false)
|
||||
@ -2036,6 +2051,20 @@ function selSeg(s)
|
||||
requestJson(obj);
|
||||
}
|
||||
|
||||
function selGrp(g)
|
||||
{
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
var sel = gId(`segcont`).querySelectorAll(`div[data-group="${g}"]`);
|
||||
var obj = {"seg":[]};
|
||||
for (let i=0; i<=lSeg; i++) obj.seg.push({"id":i,"sel":false});
|
||||
if (sel) for (let s of sel||[]) {
|
||||
let i = parseInt(s.id.substring(3));
|
||||
obj.seg[i] = {"id":i,"sel":true};
|
||||
}
|
||||
if (obj.seg.length) requestJson(obj);
|
||||
}
|
||||
|
||||
function rptSeg(s)
|
||||
{
|
||||
//TODO: 2D support
|
||||
@ -2156,6 +2185,14 @@ function setTp(s)
|
||||
requestJson(obj);
|
||||
}
|
||||
|
||||
function setGrp(s, g)
|
||||
{
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
var obj = {"seg": {"id": s, "group": g}};
|
||||
requestJson(obj);
|
||||
}
|
||||
|
||||
function setSegPwr(s)
|
||||
{
|
||||
var pwr = gId(`seg${s}pwr`).classList.contains('act');
|
||||
|
3896
wled00/html_ui.h
3896
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -92,8 +92,11 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
|
||||
if ((spc>0 && spc!=seg.spacing) || seg.map1D2D!=map1D2D) seg.fill(BLACK); // clear spacing gaps
|
||||
|
||||
seg.map1D2D = constrain(map1D2D, 0, 7);
|
||||
seg.soundSim = constrain(soundSim, 0, 7);
|
||||
seg.map1D2D = constrain(map1D2D, 0, 3);
|
||||
seg.soundSim = constrain(soundSim, 0, 3);
|
||||
|
||||
uint8_t group = elem[F("group")] | seg.group;
|
||||
seg.group = constrain(group, 0, 3);
|
||||
|
||||
uint16_t len = 1;
|
||||
if (stop > start) len = stop - start;
|
||||
@ -459,6 +462,7 @@ void serializeSegment(JsonObject& root, Segment& seg, byte id, bool forPreset, b
|
||||
byte segbri = seg.opacity;
|
||||
root["bri"] = (segbri) ? segbri : 255;
|
||||
root["cct"] = seg.cct;
|
||||
root[F("group")] = seg.group;
|
||||
|
||||
if (segmentBounds && seg.name != nullptr) root["n"] = reinterpret_cast<const char *>(seg.name); //not good practice, but decreases required JSON buffer
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user