"unrestricted" number of custom palettes (#4932)
- allow more than 10 custom palettes - move palettes into CPP file - Fix for minimizing cpal.htm (saves 2k of flash) - shortened names in cpal, saves about 400 bytes of Flash after packing - removed async from common.js loading to prevent errors on page loads if the file is not cached - restricted nubmer of user palettes on ESP8266 to 10 - unrestricted number of user palettes on all other platforms (total max palettes: 256) - added a warning when adding more than 10 palettes to let the user decide to risk it - Bugfixes in palette enumeration, fixed AR palette adding - AR palettes are now also added if there are more than 10 custom palettes Co-authored-by: Blaž Kristan <blaz@kristan-sp.si>
This commit is contained in:
@@ -143,7 +143,7 @@ async function writeHtmlGzipped(sourceFile, resultFile, page) {
|
|||||||
console.info("Minified and compressed " + sourceFile + " from " + originalLength + " to " + result.length + " bytes");
|
console.info("Minified and compressed " + sourceFile + " from " + originalLength + " to " + result.length + " bytes");
|
||||||
const array = hexdump(result);
|
const array = hexdump(result);
|
||||||
let src = singleHeader;
|
let src = singleHeader;
|
||||||
src += `const uint16_t PAGE_${page}_L = ${result.length};\n`;
|
src += `const uint16_t PAGE_${page}_length = ${result.length};\n`;
|
||||||
src += `const uint8_t PAGE_${page}[] PROGMEM = {\n${array}\n};\n\n`;
|
src += `const uint8_t PAGE_${page}[] PROGMEM = {\n${array}\n};\n\n`;
|
||||||
console.info("Writing " + resultFile);
|
console.info("Writing " + resultFile);
|
||||||
fs.writeFileSync(resultFile, src);
|
fs.writeFileSync(resultFile, src);
|
||||||
@@ -244,9 +244,22 @@ if (isAlreadyBuilt("wled00/data") && process.argv[2] !== '--force' && process.ar
|
|||||||
|
|
||||||
writeHtmlGzipped("wled00/data/index.htm", "wled00/html_ui.h", 'index');
|
writeHtmlGzipped("wled00/data/index.htm", "wled00/html_ui.h", 'index');
|
||||||
writeHtmlGzipped("wled00/data/pixart/pixart.htm", "wled00/html_pixart.h", 'pixart');
|
writeHtmlGzipped("wled00/data/pixart/pixart.htm", "wled00/html_pixart.h", 'pixart');
|
||||||
writeHtmlGzipped("wled00/data/cpal/cpal.htm", "wled00/html_cpal.h", 'cpal');
|
//writeHtmlGzipped("wled00/data/cpal/cpal.htm", "wled00/html_cpal.h", 'cpal');
|
||||||
writeHtmlGzipped("wled00/data/pxmagic/pxmagic.htm", "wled00/html_pxmagic.h", 'pxmagic');
|
writeHtmlGzipped("wled00/data/pxmagic/pxmagic.htm", "wled00/html_pxmagic.h", 'pxmagic');
|
||||||
|
|
||||||
|
writeChunks(
|
||||||
|
"wled00/data/cpal",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
file: "cpal.htm",
|
||||||
|
name: "PAGE_cpal",
|
||||||
|
method: "gzip",
|
||||||
|
filter: "html-minify"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"wled00/html_cpal.h"
|
||||||
|
);
|
||||||
|
|
||||||
writeChunks(
|
writeChunks(
|
||||||
"wled00/data",
|
"wled00/data",
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -1981,7 +1981,7 @@ void AudioReactive::createAudioPalettes(void) {
|
|||||||
if (palettes) return;
|
if (palettes) return;
|
||||||
DEBUG_PRINTLN(F("Adding audio palettes."));
|
DEBUG_PRINTLN(F("Adding audio palettes."));
|
||||||
for (int i=0; i<MAX_PALETTES; i++)
|
for (int i=0; i<MAX_PALETTES; i++)
|
||||||
if (customPalettes.size() < 10) {
|
if (customPalettes.size() < WLED_MAX_CUSTOM_PALETTES) {
|
||||||
customPalettes.push_back(CRGBPalette16(CRGB(BLACK)));
|
customPalettes.push_back(CRGBPalette16(CRGB(BLACK)));
|
||||||
palettes++;
|
palettes++;
|
||||||
DEBUG_PRINTLN(palettes);
|
DEBUG_PRINTLN(palettes);
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
Parts of the code adapted from WLED Sound Reactive
|
Parts of the code adapted from WLED Sound Reactive
|
||||||
*/
|
*/
|
||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
#include "palettes.h"
|
|
||||||
|
|
||||||
// setUpMatrix() - constructs ledmap array from matrix of panels with WxH pixels
|
// setUpMatrix() - constructs ledmap array from matrix of panels with WxH pixels
|
||||||
// this converts physical (possibly irregular) LED arrangement into well defined
|
// this converts physical (possibly irregular) LED arrangement into well defined
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
*/
|
*/
|
||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
#include "FXparticleSystem.h" // TODO: better define the required function (mem service) in FX.h?
|
#include "FXparticleSystem.h" // TODO: better define the required function (mem service) in FX.h?
|
||||||
#include "palettes.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Custom per-LED mapping has moved!
|
Custom per-LED mapping has moved!
|
||||||
@@ -226,8 +225,12 @@ void Segment::resetIfRequired() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||||
if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0;
|
// there is one randomy generated palette (1) followed by 4 palettes created from segment colors (2-5)
|
||||||
if (pal > 245 && (customPalettes.size() == 0 || 255U-pal > customPalettes.size()-1)) pal = 0;
|
// those are followed by 7 fastled palettes (6-12) and 59 gradient palettes (13-71)
|
||||||
|
// then come the custom palettes (255,254,...) growing downwards from 255 (255 being 1st custom palette)
|
||||||
|
// palette 0 is a varying palette depending on effect and may be replaced by segment's color if so
|
||||||
|
// instructed in color_from_palette()
|
||||||
|
if (pal > FIXED_PALETTE_COUNT && pal <= 255-customPalettes.size()) pal = 0; // out of bounds palette
|
||||||
//default palette. Differs depending on effect
|
//default palette. Differs depending on effect
|
||||||
if (pal == 0) pal = _default_palette; // _default_palette is set in setMode()
|
if (pal == 0) pal = _default_palette; // _default_palette is set in setMode()
|
||||||
switch (pal) {
|
switch (pal) {
|
||||||
@@ -263,13 +266,13 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
|||||||
}
|
}
|
||||||
break;}
|
break;}
|
||||||
default: //progmem palettes
|
default: //progmem palettes
|
||||||
if (pal>245) {
|
if (pal > 255 - customPalettes.size()) {
|
||||||
targetPalette = customPalettes[255-pal]; // we checked bounds above
|
targetPalette = customPalettes[255-pal]; // we checked bounds above
|
||||||
} else if (pal < 13) { // palette 6 - 12, fastled palettes
|
} else if (pal < DYNAMIC_PALETTE_COUNT+FASTLED_PALETTE_COUNT+1) { // palette 6 - 12, fastled palettes
|
||||||
targetPalette = *fastledPalettes[pal-6];
|
targetPalette = *fastledPalettes[pal-DYNAMIC_PALETTE_COUNT-1];
|
||||||
} else {
|
} else {
|
||||||
byte tcp[72];
|
byte tcp[72];
|
||||||
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[pal-13])), 72);
|
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[pal-(DYNAMIC_PALETTE_COUNT+FASTLED_PALETTE_COUNT)-1])), 72);
|
||||||
targetPalette.loadDynamicGradientPalette(tcp);
|
targetPalette.loadDynamicGradientPalette(tcp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -573,8 +576,7 @@ Segment &Segment::setMode(uint8_t fx, bool loadDefaults) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Segment &Segment::setPalette(uint8_t pal) {
|
Segment &Segment::setPalette(uint8_t pal) {
|
||||||
if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes
|
if (pal <= 255-customPalettes.size() && pal > FIXED_PALETTE_COUNT) pal = 0; // not built in palette or custom palette
|
||||||
if (pal > 245 && (customPalettes.size() == 0 || 255U-pal > customPalettes.size()-1)) pal = 0; // custom palettes
|
|
||||||
if (pal != palette) {
|
if (pal != palette) {
|
||||||
//DEBUG_PRINTF_P(PSTR("- Starting palette transition: %d\n"), pal);
|
//DEBUG_PRINTF_P(PSTR("- Starting palette transition: %d\n"), pal);
|
||||||
startTransition(strip.getTransition(), blendingStyle != BLEND_STYLE_FADE); // start transition prior to change (no need to copy segment)
|
startTransition(strip.getTransition(), blendingStyle != BLEND_STYLE_FADE); // start transition prior to change (no need to copy segment)
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ void loadCustomPalettes() {
|
|||||||
byte tcp[72]; //support gradient palettes with up to 18 entries
|
byte tcp[72]; //support gradient palettes with up to 18 entries
|
||||||
CRGBPalette16 targetPalette;
|
CRGBPalette16 targetPalette;
|
||||||
customPalettes.clear(); // start fresh
|
customPalettes.clear(); // start fresh
|
||||||
for (int index = 0; index<10; index++) {
|
for (int index = 0; index < WLED_MAX_CUSTOM_PALETTES; index++) {
|
||||||
char fileName[32];
|
char fileName[32];
|
||||||
sprintf_P(fileName, PSTR("/palette%d.json"), index);
|
sprintf_P(fileName, PSTR("/palette%d.json"), index);
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ CRGBPalette16 generateHarmonicRandomPalette(const CRGBPalette16 &basepalette);
|
|||||||
CRGBPalette16 generateRandomPalette();
|
CRGBPalette16 generateRandomPalette();
|
||||||
void loadCustomPalettes();
|
void loadCustomPalettes();
|
||||||
extern std::vector<CRGBPalette16> customPalettes;
|
extern std::vector<CRGBPalette16> customPalettes;
|
||||||
inline size_t getPaletteCount() { return 13 + GRADIENT_PALETTE_COUNT + customPalettes.size(); }
|
inline size_t getPaletteCount() { return FIXED_PALETTE_COUNT + customPalettes.size(); }
|
||||||
inline uint32_t colorFromRgbw(byte* rgbw) { return uint32_t((byte(rgbw[3]) << 24) | (byte(rgbw[0]) << 16) | (byte(rgbw[1]) << 8) | (byte(rgbw[2]))); }
|
inline uint32_t colorFromRgbw(byte* rgbw) { return uint32_t((byte(rgbw[3]) << 24) | (byte(rgbw[0]) << 16) | (byte(rgbw[1]) << 8) | (byte(rgbw[2]))); }
|
||||||
void hsv2rgb(const CHSV32& hsv, uint32_t& rgb);
|
void hsv2rgb(const CHSV32& hsv, uint32_t& rgb);
|
||||||
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb);
|
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb);
|
||||||
@@ -141,4 +141,8 @@ void setRandomColor(byte* rgb);
|
|||||||
|
|
||||||
[[gnu::hot, gnu::pure]] uint32_t color_fade(uint32_t c1, uint8_t amount, bool video = false);
|
[[gnu::hot, gnu::pure]] uint32_t color_fade(uint32_t c1, uint8_t amount, bool video = false);
|
||||||
|
|
||||||
|
// palettes
|
||||||
|
extern const TProgmemRGBPalette16* const fastledPalettes[];
|
||||||
|
extern const uint8_t* const gGradientPalettes[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,15 @@
|
|||||||
* Readability defines and their associated numerical values + compile-time constants
|
* Readability defines and their associated numerical values + compile-time constants
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define GRADIENT_PALETTE_COUNT 59
|
constexpr size_t FASTLED_PALETTE_COUNT = 7; // = sizeof(fastledPalettes) / sizeof(fastledPalettes[0]);
|
||||||
|
constexpr size_t GRADIENT_PALETTE_COUNT = 59; // = sizeof(gGradientPalettes) / sizeof(gGradientPalettes[0]);
|
||||||
|
constexpr size_t DYNAMIC_PALETTE_COUNT = 5; // 1-5 are dynamic palettes (1=random,2=primary,3=primary+secondary,4=primary+secondary+tertiary,5=primary+secondary(+tertiary if not black)
|
||||||
|
constexpr size_t FIXED_PALETTE_COUNT = DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT + GRADIENT_PALETTE_COUNT; // total number of fixed palettes
|
||||||
|
#ifndef ESP8266
|
||||||
|
#define WLED_MAX_CUSTOM_PALETTES (255 - FIXED_PALETTE_COUNT) // allow up to 255 total palettes, user is warned about stability issues when adding more than 10
|
||||||
|
#else
|
||||||
|
#define WLED_MAX_CUSTOM_PALETTES 10 // ESP8266: limit custom palettes to 10
|
||||||
|
#endif
|
||||||
|
|
||||||
// You can define custom product info from build flags.
|
// You can define custom product info from build flags.
|
||||||
// This is useful to allow API consumer to identify what type of WLED version
|
// This is useful to allow API consumer to identify what type of WLED version
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
function gId(e) {return d.getElementById(e);}
|
function gId(e) {return d.getElementById(e);}
|
||||||
function cE(e) {return d.createElement(e);}
|
function cE(e) {return d.createElement(e);}
|
||||||
</script>
|
</script>
|
||||||
|
<script src="common.js" type="text/javascript"></script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
@@ -21,39 +22,39 @@
|
|||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
line-height: 0.5;
|
line-height: 0.5;
|
||||||
}
|
}
|
||||||
#parent-container {
|
#pCont {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
#bottomContainer {
|
#bCont {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
}
|
}
|
||||||
#gradient-box {
|
#gBox {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
.color-marker, .color-picker-marker {
|
.cMark, .cPickMark {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background-color: rgb(192, 192, 192);
|
background-color: rgb(192, 192, 192);
|
||||||
border: 2px solid rgba(68, 68, 68, 0.5);
|
border: 2px solid rgba(68, 68, 68, 0.5);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
.color-marker {
|
.cMark {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
width: 7px;
|
width: 7px;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
}
|
}
|
||||||
.color-picker-marker {
|
.cPickMark {
|
||||||
height: 7px;
|
height: 7px;
|
||||||
width: 7px;
|
width: 7px;
|
||||||
top: 150%;
|
top: 150%;
|
||||||
}
|
}
|
||||||
.delete-marker {
|
.dMark {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 5px;
|
height: 5px;
|
||||||
width: 5px;
|
width: 5px;
|
||||||
@@ -63,7 +64,7 @@
|
|||||||
top: 220%;
|
top: 220%;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
.color-picker {
|
.cPick {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
@@ -73,13 +74,13 @@
|
|||||||
border-color: #111;
|
border-color: #111;
|
||||||
background-color: #111;
|
background-color: #111;
|
||||||
}
|
}
|
||||||
.buttonclass {
|
.btnCls {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
background-color: #111;
|
background-color: #111;
|
||||||
}
|
}
|
||||||
#bottomContainer span {
|
#bCont span {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@@ -87,7 +88,6 @@
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
#info {
|
#info {
|
||||||
display: "";
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -104,119 +104,76 @@
|
|||||||
width: 800px;
|
width: 800px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.palette {
|
.pal {height: 20px;}
|
||||||
height: 20px;
|
.pGrads {flex: 1; height: 20px; border-radius: 3px;}
|
||||||
}
|
.pMain {margin-top: 50px; width: 100%;}
|
||||||
.paletteGradients {
|
.pTop {height: fit-content; text-align: center; color: #fff; font-size: 14px; line-height: 1;}
|
||||||
flex: 1;
|
.pGradPar {display: flex; align-items: center; height: fit-content; margin-top: 10px; text-align: center; color: #fff; font-size: 12px; line-height: 1;}
|
||||||
height: 20px;
|
.btnsDiv {display: inline-flex; margin-left: 5px; width: 50px;}
|
||||||
border-radius: 3px;
|
.sSpan, .eSpan {cursor: pointer;}
|
||||||
}
|
h1 {font-size: 1.6rem;}
|
||||||
.palettesMain {
|
|
||||||
margin-top: 50px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.palTop {
|
|
||||||
height: fit-content;
|
|
||||||
text-align: center;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 12px;
|
|
||||||
position: relative;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
.palGradientParent {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: fit-content;
|
|
||||||
margin-top: 10px;
|
|
||||||
text-align: center;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 12px;
|
|
||||||
position: relative;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
.buttonsDiv {
|
|
||||||
display: inline-flex;
|
|
||||||
margin-left: 5px;
|
|
||||||
width: 50px;
|
|
||||||
}
|
|
||||||
.sendSpan, .editSpan{
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: 1.6rem;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="wrap" class="wrap">
|
<div id="wrap" class="wrap">
|
||||||
<div style="display: flex; justify-content: center;">
|
<div style="display: flex; justify-content: center;">
|
||||||
<h1 style="display: flex; align-items: center;">
|
<h1 style="display: flex; align-items: center;">
|
||||||
<svg style="width:36px;height:36px;margin-right:6px;" viewBox="0 0 32 32">
|
<svg style="width: 36px; height: 36px; margin-right: 6px;" viewBox="0 0 32 32">
|
||||||
<rect style="fill:#003FFF" x="6" y="22" width="8" height="4"/>
|
<rect style="fill: #03F" x="6" y="22" width="8" height="4"/>
|
||||||
<rect style="fill:#003FFF" x="14" y="14" width="4" height="8"/>
|
<rect style="fill: #03F" x="14" y="14" width="4" height="8"/>
|
||||||
<rect style="fill:#003FFF" x="18" y="10" width="4" height="8"/>
|
<rect style="fill: #03F" x="18" y="10" width="4" height="8"/>
|
||||||
<rect style="fill:#003FFF" x="22" y="6" width="8" height="4"/>
|
<rect style="fill: #03F" x="22" y="6" width="8" height="4"/>
|
||||||
</svg>
|
</svg>
|
||||||
<span id="head">WLED Custom Palette Editor</span>
|
<span id="head">WLED Palette Editor</span>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="parent-container">
|
<div id="pCont"><div id="gBox"></div></div>
|
||||||
<div id="gradient-box"></div>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; justify-content: center;">
|
<div style="display: flex; justify-content: center;">
|
||||||
<div id="palettes" class="palettesMain">
|
<div id="pals" class="pMain">
|
||||||
<div id="distDiv" class="palTop"></div>
|
<div id="distDiv" class="pTop"></div>
|
||||||
<div id="palTop" class="palTop">
|
<div id="memWarn" class="pTop" style="display:none; color:#ff6600; margin-bottom:8px; font-size:16px;">
|
||||||
Currently in use custom palettes
|
Warning: Adding many custom palettes might cause stability issues, create <a href="/settings/sec#backup" style="color:#ff9900">backups</a> before proceeding.</div>
|
||||||
</div>
|
<div id="pTop" class="pTop">Custom palettes</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: flex; justify-content: center;">
|
<div style="display: flex; justify-content: center;">
|
||||||
<div id="info">
|
<div id="info">Click gradient to add. Box = color. Red = delete. Arrow = upload. Pencil = edit.</div>
|
||||||
Click on the gradient editor to add new color slider, then the colored box below the slider to change its color.
|
|
||||||
Click the red box below indicator (and confirm) to delete.
|
|
||||||
Once finished, click the arrow icon to upload into the desired slot.
|
|
||||||
To edit existing palette, click the pencil icon.
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; justify-content: center;">
|
<div style="display: flex; justify-content: center;">
|
||||||
<div id="staticPalettes" class="palettesMain">
|
<div id="sPals" class="pMain">
|
||||||
<div id="statpalTop" class="palTop">
|
<div id="spTop" class="pTop">Static palettes</div>
|
||||||
Available static palettes
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
//global variables
|
// global vars
|
||||||
var gradientBox = gId('gradient-box');
|
var gBox = gId('gBox'); // gradientBox
|
||||||
var cpalc = -1;
|
var cpalc = -1, cpalm = 10; // current palette count, max custom
|
||||||
var pxCol = {};
|
var pxCol = {}; // pixel color map
|
||||||
var tCol = {};
|
var tCol = {}; // true color map
|
||||||
var rect = gradientBox.getBoundingClientRect();
|
var rect = gBox.getBoundingClientRect(); // bounding rect of gBox
|
||||||
var gradientLength = rect.width;
|
var gLen = rect.width; // gradientLength
|
||||||
var mOffs = Math.round((gradientLength / 256) / 2) - 5;
|
var mOffs = Math.round((gLen / 256) / 2) - 5; // marker offset
|
||||||
var paletteArray = []; //Holds the palettes after load.
|
var palArr = []; // paletteArray
|
||||||
var paletteName = []; // Holds the names of the palettes after load.
|
var palNm = []; // paletteName
|
||||||
|
|
||||||
var svgSave = '<svg style="width:25px;height:25px" viewBox="0 0 24 24"><path fill=#fff d="M22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2A10,10 0 0,1 22,12M7,12L12,17V14H16V10H12V7L7,12Z"/></svg>'
|
var svgSave = '<svg style="width:25px;height:25px" viewBox="0 0 24 24"><path fill=#fff d="M22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2A10,10 0 0,1 22,12M7,12L12,17V14H16V10H12V7L7,12Z"/></svg>'
|
||||||
var svgEdit = '<svg style="width:25px;height:25px" viewBox="0 0 24 24"><path fill=#fff d="M12,2C6.47,2 2,6.47 2,12C2,17.53 6.47,22 12,22C17.53,22 22,17.53 22,12C22,6.47 17.53,2 12,2M15.1,7.07C15.24,7.07 15.38,7.12 15.5,7.23L16.77,8.5C17,8.72 17,9.07 16.77,9.28L15.77,10.28L13.72,8.23L14.72,7.23C14.82,7.12 14.96,7.07 15.1,7.07M13.13,8.81L15.19,10.87L9.13,16.93H7.07V14.87L13.13,8.81Z"/></svg>'
|
var svgEdit = '<svg style="width:25px;height:25px" viewBox="0 0 24 24"><path fill=#fff d="M12,2C6.47,2 2,6.47 2,12C2,17.53 6.47,22 12,22C17.53,22 22,17.53 22,12C22,6.47 17.53,2 12,2M15.1,7.07C15.24,7.07 15.38,7.12 15.5,7.23L16.77,8.5C17,8.72 17,9.07 16.77,9.28L15.77,10.28L13.72,8.23L14.72,7.23C14.82,7.12 14.96,7.07 15.1,7.07M13.13,8.81L15.19,10.87L9.13,16.93H7.07V14.87L13.13,8.81Z"/></svg>'
|
||||||
var svgDist = '<svg style="width:25px;height:25px" viewBox="0 0 24 24"><path fill=#fff d="M4 22H2V2H4V22M22 2H20V22H22V2M13.5 7H10.5V17H13.5V7Z"/></svg>'
|
var svgDist = '<svg style="width:25px;height:25px" viewBox="0 0 24 24"><path fill=#fff d="M4 22H2V2H4V22M22 2H20V22H22V2M13.5 7H10.5V17H13.5V7Z"/></svg>'
|
||||||
var svgTrash = '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" width="30px" height="30px"><path style="fill:#880000; stroke: #888888; stroke-width: -2px;stroke-dasharray: 0.1, 8;" d="M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M7,6H17V19H7V6M9,8V17H11V8H9M13,8V17H15V8H13Z"/></svg>'
|
var svgTrash = '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" width="30px" height="30px"><path style="fill:#880000; stroke: #888888; stroke-width: -2px;stroke-dasharray: 0.1, 8;" d="M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M7,6H17V19H7V6M9,8V17H11V8H9M13,8V17H15V8H13Z"/></svg>'
|
||||||
|
|
||||||
const distDiv = gId("distDiv");
|
const distDiv = gId("distDiv");
|
||||||
distDiv.addEventListener('click', distribute);
|
distDiv.addEventListener('click', distrib);
|
||||||
distDiv.setAttribute('title', 'Distribute colors equally');
|
distDiv.setAttribute('title', 'Distribute equally');
|
||||||
distDiv.innerHTML = svgDist;
|
distDiv.innerHTML = svgDist;
|
||||||
|
|
||||||
function recOf() {
|
function recOf() {
|
||||||
rect = gradientBox.getBoundingClientRect();
|
rect = gBox.getBoundingClientRect();
|
||||||
gradientLength = rect.width;
|
gLen = rect.width;
|
||||||
mOffs = Math.round((gradientLength / 256) / 2) - 5;
|
mOffs = Math.round((gLen / 256) / 2) - 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Initiation
|
//Initiation
|
||||||
@@ -224,277 +181,220 @@
|
|||||||
window.addEventListener('load', chkW);
|
window.addEventListener('load', chkW);
|
||||||
window.addEventListener('resize', chkW);
|
window.addEventListener('resize', chkW);
|
||||||
|
|
||||||
gradientBox.addEventListener("click", clikOnGradient);
|
gBox.addEventListener("click", clikGrad);
|
||||||
|
|
||||||
//Sets start and stop, mandatory
|
//Sets start and stop, mandatory
|
||||||
addC(0);
|
addC(0);
|
||||||
addC(255);
|
addC(255);
|
||||||
|
|
||||||
updateGradient(); //Sets the gradient at startup
|
updGrad(); // updateGradient at startup
|
||||||
|
|
||||||
function clikOnGradient(e) {
|
function clikGrad(e) { // clickOnGradient
|
||||||
removeTrashcan(e);
|
rmTrash(e); // removeTrashcan
|
||||||
addC(Math.round((e.offsetX/gradientLength)*256));
|
addC(Math.round((e.offsetX/gLen)*256));
|
||||||
}
|
}
|
||||||
|
|
||||||
///////// Add a new colorMarker
|
///////// Add a new color marker
|
||||||
function addC(truePos, thisColor = '') {
|
function addC(tPos, thisCol = '') {
|
||||||
let position = -1;
|
let pos = -1;
|
||||||
let iExist = false;
|
let exist = false;
|
||||||
const colorMarkers = gradientBox.querySelectorAll('.color-marker');
|
const cMarks = gBox.querySelectorAll('.cMark'); // color markers
|
||||||
|
|
||||||
colorMarkers.forEach((colorMarker, i) => {
|
cMarks.forEach((cm) => {
|
||||||
if (colorMarker.getAttribute("data-truepos") == truePos) {
|
if (cm.getAttribute("data-tpos") == tPos) exist = true;
|
||||||
iExist = true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (colorMarkers.length > 17) iExist = true;
|
if (cMarks.length > 17) exist = true;
|
||||||
if (iExist) return; // Exit the function early if iExist is true
|
if (exist) return;
|
||||||
|
|
||||||
if (truePos > 0 && truePos < 255) {
|
if (tPos > 0 && tPos < 255) {
|
||||||
//calculate first available > 0
|
for (var i=1; i<=16 && pos<1; i++) {
|
||||||
for (var i = 1; i <= 16 && position < 1; i++) {
|
if (!gId("cMark"+i)) pos = i;
|
||||||
if (!gId("colorMarker"+i)) {
|
|
||||||
position = i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else{
|
} else {
|
||||||
position = truePos;
|
pos = tPos;
|
||||||
}
|
}
|
||||||
if (thisColor == ''){
|
if (thisCol == '') {
|
||||||
thisColor = `#${(Math.random() * 0xFFFFFF << 0).toString(16).padStart(6, '0')}`;// set random color as default
|
thisCol = `#${(Math.random()*0xFFFFFF<<0).toString(16).padStart(6,'0')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const colorMarker = cE('span'); // create a marker for the color position
|
const cMark = cE('span'); // color marker
|
||||||
colorMarker.className = 'color-marker';
|
cMark.className = 'cMark';
|
||||||
colorMarker.id = 'colorMarker' + position.toString();
|
cMark.id = 'cMark' + pos;
|
||||||
colorMarker.setAttribute("data-truepos", truePos); //Used to always have a true position no matter what screen or percentage we use
|
cMark.setAttribute("data-tpos", tPos);
|
||||||
colorMarker.setAttribute("data-truecol", thisColor); //Used to hold the color of the position in the gradient connected to a true position
|
cMark.setAttribute("data-tcol", thisCol);
|
||||||
colorMarker.setAttribute("data-offset", mOffs);
|
cMark.setAttribute("data-offset", mOffs);
|
||||||
colorMarker.addEventListener('click', stopFurtherProp); //Added to prevent the gradient click to fire when covered by a marker
|
cMark.addEventListener('click', stopProp);
|
||||||
colorMarker.style.left = `${Math.round((gradientLength / 256) * truePos)+mOffs}px`;
|
cMark.style.left = `${Math.round((gLen/256)*tPos)+mOffs}px`;
|
||||||
|
|
||||||
const colorPicker = cE('input');
|
const cPick = cE('input'); // colorPicker
|
||||||
colorPicker.type = 'color';
|
cPick.type = 'color';
|
||||||
colorPicker.value = thisColor;
|
cPick.value = thisCol;
|
||||||
colorPicker.className = 'color-picker';
|
cPick.className = 'cPick';
|
||||||
colorPicker.id = 'colorPicker' + position.toString();
|
cPick.id = 'cPick' + pos;
|
||||||
colorPicker.addEventListener('input', updateGradient);
|
cPick.addEventListener('input', updGrad);
|
||||||
colorPicker.addEventListener('click',cpClk)
|
cPick.addEventListener('click', cpClk);
|
||||||
|
|
||||||
const colorPickerMarker = cE('span'); // create a marker for the color position
|
const cPM = cE('span'); // colorPickerMarker
|
||||||
colorPickerMarker.className = 'color-picker-marker';
|
cPM.className = 'cPickMark';
|
||||||
colorPickerMarker.id = 'colorPickerMarker' + position.toString();
|
cPM.id = 'cPM' + pos;
|
||||||
colorPickerMarker.addEventListener('click', colClk);
|
cPM.addEventListener('click', colClk);
|
||||||
colorPickerMarker.style.left = colorMarker.style.left;
|
cPM.style.left = cMark.style.left;
|
||||||
colorPicker.style.left = colorMarker.style.left;
|
cPick.style.left = cMark.style.left;
|
||||||
|
|
||||||
const deleteMarker = cE('span'); // create a delete marker for the color position
|
if (pos > 0 && pos < 255) {
|
||||||
if (position > 0 && position < 255) {
|
const dMark = cE('span'); // deleteMarker
|
||||||
deleteMarker.className = 'delete-marker';
|
dMark.className = 'dMark';
|
||||||
deleteMarker.id = 'deleteMarker' + position.toString();
|
dMark.id = 'dMark' + pos;
|
||||||
deleteMarker.addEventListener('click', (e) => {
|
dMark.addEventListener('click', (e) => { delCol(e); });
|
||||||
deleteColor(e);
|
dMark.style.left = cMark.style.left;
|
||||||
});
|
gBox.appendChild(dMark);
|
||||||
deleteMarker.style.left = colorMarker.style.left
|
|
||||||
}
|
}
|
||||||
|
|
||||||
colorMarker.style.backgroundColor = colorPicker.value; // set marker color to match color picker
|
cMark.style.backgroundColor = cPick.value;
|
||||||
colorPickerMarker.style.backgroundColor = colorPicker.value;
|
cPM.style.backgroundColor = cPick.value;
|
||||||
|
|
||||||
gradientBox.appendChild(colorPicker);
|
gBox.appendChild(cPick);
|
||||||
gradientBox.appendChild(colorMarker);
|
gBox.appendChild(cMark);
|
||||||
gradientBox.appendChild(colorPickerMarker);
|
gBox.appendChild(cPM);
|
||||||
if (position != 0 && position != 255) gradientBox.appendChild(deleteMarker); // append the marker if not start or end
|
if (pos > 0 && pos < 255) mkDrag(gId(cMark.id)); // makeMeDrag
|
||||||
//make markers slidable IF they are not the first or last slider
|
|
||||||
if (position > 0 && position < 255) makeMeDrag(gId(colorMarker.id));
|
|
||||||
|
|
||||||
setTooltipMarker(gId(colorMarker.id));
|
setTip(gId(cMark.id)); // setTooltipMarker
|
||||||
|
updGrad();
|
||||||
updateGradient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////// Update Gradient
|
///////// Update Gradient
|
||||||
function updateGradient() {
|
function updGrad() { // updateGradient
|
||||||
const colorMarkers = gradientBox.querySelectorAll('.color-marker');
|
const cMarks = gBox.querySelectorAll('.cMark');
|
||||||
pxCol = {};
|
pxCol = {};
|
||||||
tCol = {}
|
tCol = {};
|
||||||
colorMarkers.forEach((colorMarker, index) => {
|
cMarks.forEach((cm) => {
|
||||||
const thisColorPicker = gId(colorMarkers[index].id.replace('colorMarker', 'colorPicker'));
|
const cp = gId(cm.id.replace('cMark','cPick'));
|
||||||
const colorToSet = thisColorPicker.value;
|
const col = cp.value;
|
||||||
gId(colorMarkers[index].id.replace('colorMarker', 'colorPickerMarker')).style.backgroundColor = colorToSet;
|
gId(cm.id.replace('cMark','cPM')).style.backgroundColor = col;
|
||||||
colorMarkers[index].style.backgroundColor = colorToSet;
|
cm.style.backgroundColor = col;
|
||||||
colorMarkers[index].setAttribute("data-truecol", colorToSet);
|
cm.setAttribute("data-tcol", col);
|
||||||
const tPos = colorMarkers[index].getAttribute("data-truepos");
|
const tPos = cm.getAttribute("data-tpos");
|
||||||
const gradientPos = Math.round((gradientLength / 256)*tPos);
|
const gPos = Math.round((gLen/256)*tPos);
|
||||||
pxCol[gradientPos] = colorToSet;
|
pxCol[gPos] = col;
|
||||||
tCol[tPos] = colorToSet;
|
tCol[tPos] = col;
|
||||||
});
|
});
|
||||||
gradientString = 'linear-gradient(to right';
|
let gStr = 'linear-gradient(to right';
|
||||||
Object.entries(pxCol).forEach(([p, c]) => {
|
Object.entries(pxCol).forEach(([p,c]) => {
|
||||||
gradientString += `, ${c} ${p}px`;
|
gStr += `, ${c} ${p}px`;
|
||||||
});
|
});
|
||||||
gradientString += ')';
|
gStr += ')';
|
||||||
gradientBox.style.background = gradientString;
|
gBox.style.background = gStr;
|
||||||
//gId("jsonstring").innerHTML = calcJSON();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopFurtherProp(e) {
|
function stopProp(e) { e.stopPropagation(); }
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
function colClk(e){
|
function colClk(e) {
|
||||||
removeTrashcan(e)
|
rmTrash(e);
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
let cp = gId(e.srcElement.id.replace("Marker",""));
|
const src = e.target || e.srcElement;
|
||||||
|
let cp = gId(src.id.replace("M","")); // marker → picker
|
||||||
cp.click();
|
cp.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
function cpClk(e) {
|
function cpClk(e) {
|
||||||
removeTrashcan(event)
|
rmTrash(e);
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
//This neat little function makes any element draggable on the X-axis.
|
// make element draggable
|
||||||
//Just call: makeMeDrag(myElement); And you are good to go.
|
function mkDrag(el) { // makeMeDrag
|
||||||
function makeMeDrag(elmnt) {
|
var posNew=0, mPos=0;
|
||||||
var posNew = 0, mousePos = 0, mouseOffset = 0
|
var rect=gBox.getBoundingClientRect();
|
||||||
|
var maxX=rect.right, minX=rect.left, gLen=maxX-minX+1;
|
||||||
|
|
||||||
//Set these to whatever you want to limit your movement to
|
el.onmousedown=dragStart;
|
||||||
var rect = gradientBox.getBoundingClientRect();
|
el.ontouchstart=dragStart;
|
||||||
var maxX = rect.right; // maximum X coordinate
|
|
||||||
var minX = rect.left; // minimum X coordinate i.e. also offset from left of screen
|
|
||||||
var gradientLength = maxX - minX + 1;
|
|
||||||
|
|
||||||
elmnt.onmousedown = dragMouseDown;
|
function dragStart(e) {
|
||||||
elmnt.ontouchstart = dragMouseDown;
|
rmTrash(e);
|
||||||
|
var isT=e.type.startsWith('touch');
|
||||||
function dragMouseDown(e) {
|
if (!isT) e.preventDefault();
|
||||||
removeTrashcan(event)
|
mPos=isT?e.touches[0].clientX:e.clientX;
|
||||||
e = e || window.event;
|
d.onmouseup=dragEnd; d.ontouchend=dragEnd; d.ontouchcancel=dragEnd;
|
||||||
var isTouch = e.type.startsWith('touch');
|
d.onmousemove=dragMove; d.ontouchmove=dragMove;
|
||||||
if (!isTouch) e.preventDefault();
|
|
||||||
// get the mouse cursor position at startup:
|
|
||||||
mousePos = isTouch ? e.touches[0].clientX : e.clientX;
|
|
||||||
d.onmouseup = closeDragElement;
|
|
||||||
d.ontouchcancel = closeDragElement;
|
|
||||||
d.ontouchend = closeDragElement;
|
|
||||||
// call a function whenever the cursor moves:
|
|
||||||
d.onmousemove = elementDrag;
|
|
||||||
d.ontouchmove = elementDrag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function elementDrag(e) {
|
function dragMove(e) {
|
||||||
e = e || window.event;
|
var isT=e.type.startsWith('touch');
|
||||||
var isTouch = e.type.startsWith('touch');
|
if (!isT) e.preventDefault();
|
||||||
if (!isTouch) e.preventDefault();
|
var cX=isT?e.touches[0].clientX:e.clientX;
|
||||||
// calculate the new cursor position:
|
posNew=mPos-cX; mPos=cX;
|
||||||
var clientX = isTouch ? e.touches[0].clientX : e.clientX;
|
var mInG=mPos-(minX+1);
|
||||||
posNew = mousePos - clientX;
|
var tPos=Math.round((mInG/gLen)*256);
|
||||||
mousePos = clientX;
|
var old=el.getAttribute("data-tpos");
|
||||||
mousePosInGradient = mousePos - (minX + 1)
|
if (tPos>0 && tPos<255 && old!=tPos) {
|
||||||
|
el.style.left=(Math.round((gLen/256)*tPos)+mOffs)+"px";
|
||||||
truePos = Math.round((mousePosInGradient/gradientLength)*256);
|
gId(el.id.replace('cMark','cPM')).style.left=el.style.left;
|
||||||
oldTruePos = elmnt.getAttribute("data-truepos");
|
gId(el.id.replace('cMark','dMark')).style.left=el.style.left;
|
||||||
// set the element's new position if new position within min/max limits:
|
gId(el.id.replace('cMark','cPick')).style.left=el.style.left;
|
||||||
if (truePos > 0 && truePos < 255 && oldTruePos != truePos) {
|
el.setAttribute("data-tpos",tPos);
|
||||||
if (truePos < 64) {
|
setTip(el);
|
||||||
thisOffset = 0;
|
updGrad();
|
||||||
} else if (truePos > 192) {
|
|
||||||
thisOffset = 7;
|
|
||||||
} else {
|
|
||||||
thisOffset=3;
|
|
||||||
}
|
|
||||||
elmnt.style.left = (Math.round((gradientLength/256)*truePos)+mOffs) + "px";
|
|
||||||
gId(elmnt.id.replace('colorMarker', 'colorPickerMarker')).style.left = elmnt.style.left;
|
|
||||||
gId(elmnt.id.replace('colorMarker', 'deleteMarker')).style.left = elmnt.style.left;
|
|
||||||
gId(elmnt.id.replace('colorMarker', 'colorPicker')).style.left = elmnt.style.left;
|
|
||||||
elmnt.setAttribute("data-truepos", truePos);
|
|
||||||
setTooltipMarker(elmnt);
|
|
||||||
updateGradient();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDragElement() {
|
function dragEnd() {
|
||||||
/* stop moving when mouse button is released:*/
|
d.onmouseup=null; d.ontouchend=null; d.ontouchcancel=null;
|
||||||
d.onmouseup = null;
|
d.onmousemove=null; d.ontouchmove=null;
|
||||||
d.ontouchcancel = null;
|
|
||||||
d.ontouchend = null;
|
|
||||||
d.onmousemove = null;
|
|
||||||
d.ontouchmove = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTooltipMarker(elmnt) {
|
function setTip(el) { // setTooltipMarker
|
||||||
elmnt.setAttribute('title', `${elmnt.getAttribute("data-truepos")} : ${elmnt.getAttribute("data-truecol")}`)
|
el.setAttribute('title', `${el.getAttribute("data-tpos")} : ${el.getAttribute("data-tcol")}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteColor(e) {
|
function delCol(e) { // deleteColor
|
||||||
var trash = cE("div");
|
var trash=cE("div");
|
||||||
thisDeleteMarker = e.srcElement;
|
var dM=e.target || e.srcElement;
|
||||||
thisColorMarker = gId(thisDeleteMarker.id.replace("delete", "color"));
|
var cM=gId(dM.id.replace("d","c"));
|
||||||
thisColorPickerMarker = gId(thisDeleteMarker.id.replace("delete", "colorPicker"));
|
var cPM=gId(dM.id.replace("dMark","cPM"));
|
||||||
thisColorPicker = gId(thisDeleteMarker.id.replace("deleteMarker", "colorPicker"));
|
var cP=gId(dM.id.replace("dMark","cPick"));
|
||||||
renderOffsetX = 15 - 5;
|
var rX=dM.getBoundingClientRect().x-10;
|
||||||
renderX = e.srcElement.getBoundingClientRect().x - renderOffsetX;
|
var rY=dM.getBoundingClientRect().y+13;
|
||||||
renderY = e.srcElement.getBoundingClientRect().y + 13;
|
|
||||||
|
|
||||||
trash.id = "trash";
|
trash.id="trash";
|
||||||
trash.innerHTML = svgTrash;
|
trash.innerHTML=svgTrash;
|
||||||
trash.style.position = "absolute";
|
trash.style.position="absolute";
|
||||||
trash.style.left = (renderX) + "px";
|
trash.style.left=rX+"px";
|
||||||
trash.style.top = (renderY) + "px";
|
trash.style.top=rY+"px";
|
||||||
d.body.appendChild(trash);
|
d.body.appendChild(trash);
|
||||||
|
|
||||||
trash.addEventListener("click", (e)=>{
|
trash.addEventListener("click",()=>{
|
||||||
trash.parentNode.removeChild(trash);
|
trash.remove(); cM.remove(); cPM.remove(); cP.remove(); dM.remove();
|
||||||
thisDeleteMarker.parentNode.removeChild(thisDeleteMarker);
|
updGrad();
|
||||||
thisColorPickerMarker.parentNode.removeChild(thisColorPickerMarker);
|
|
||||||
thisColorMarker.parentNode.removeChild(thisColorMarker);
|
|
||||||
thisColorPicker.parentNode.removeChild(thisColorPicker);
|
|
||||||
updateGradient();
|
|
||||||
});
|
});
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
// Add event listener to close the trashcan on outside click
|
d.addEventListener("click", rmTrash);
|
||||||
d.addEventListener("click", removeTrashcan);
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeTrashcan(event) {
|
function rmTrash(e) { // removeTrashcan
|
||||||
trash = gId("trash");
|
var t=gId("trash");
|
||||||
if (event.target != trash && trash) {
|
if (t && e.target!=t) { t.remove(); d.removeEventListener("click", rmTrash);}
|
||||||
trash.parentNode.removeChild(trash);
|
|
||||||
d.removeEventListener("click", removeTrashcan);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function chkW() {
|
function chkW() {
|
||||||
//Possibly add more code that recalculates the gradient... Massive job ;)
|
const wrap=gId('wrap'); const head=gId('head');
|
||||||
const wrap = gId('wrap');
|
head.style.display=(wrap.offsetWidth<600)?'none':'inline';
|
||||||
const head = gId('head');
|
|
||||||
if (wrap.offsetWidth < 600) {
|
|
||||||
head.style.display = 'none';
|
|
||||||
} else {
|
|
||||||
head.style.display = 'inline';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function calcJSON() {
|
function calcJSON() {
|
||||||
let rStr = '{"palette":['
|
let rStr='{"palette":[';
|
||||||
Object.entries(tCol).forEach(([p, c]) => {
|
Object.entries(tCol).forEach(([p,c],i)=>{
|
||||||
if (p > 0) rStr += ',';
|
if (i>0) rStr+=',';
|
||||||
rStr += `${p},"${c.slice(1)}"`; // store in hex notation
|
rStr+=`${p},"${c.slice(1)}"`;
|
||||||
//rStr += `${p},${parseInt(c.slice(1, 3), 16)},${parseInt(c.slice(3, 5), 16)},${parseInt(c.slice(5, 7), 16)}`;
|
|
||||||
});
|
});
|
||||||
rStr += ']}';
|
rStr+=']}';
|
||||||
return rStr;
|
return rStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
function initiateUpload(idx) {
|
function initUpload(i) {
|
||||||
const data = calcJSON();
|
uploadJSON(calcJSON(), `/palette${i}.json`);
|
||||||
const fileName = `/palette${idx}.json`;
|
|
||||||
uploadJSON(data, fileName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function uploadJSON(jsonString, fileName) {
|
function uploadJSON(jsonString, fileName) {
|
||||||
@@ -525,41 +425,38 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getInfo() {
|
async function getInfo() {
|
||||||
hst = location.host;
|
getLoc();
|
||||||
if (hst.length > 0 ) {
|
try {
|
||||||
try {
|
var arr = [];
|
||||||
var arr = [];
|
const resInfo = await fetch(getURL('/json/info')); // fetch info (includes cpalcount and cpalmax)
|
||||||
const responseInfo = await fetch('http://'+hst+'/json/info');
|
const resPals = await fetch(getURL('/json/pal')); // fetch palette names
|
||||||
const responsePalettes = await fetch('http://'+hst+'/json/palettes');
|
const json = await resInfo.json();
|
||||||
const json = await responseInfo.json();
|
palNm = await resPals.json();
|
||||||
paletteName = await responsePalettes.json();
|
cpalc = json.cpalcount;
|
||||||
cpalc = json.cpalcount;
|
cpalm = json.cpalmax;
|
||||||
fetchPalettes(cpalc-1);
|
fetchPals(cpalc-1);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error('cannot identify host');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchPalettes(lastPal) {
|
async function fetchPals(lastPal) {
|
||||||
paletteArray.length = 0;
|
palArr.length = 0;
|
||||||
for (let i = 0; i <= lastPal; i++) {
|
for (let i = 0; i <= lastPal; i++) {
|
||||||
const url = `http://${hst}/palette${i}.json`;
|
const url = getURL(`/palette${i}.json`);
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
paletteArray.push(json);
|
palArr.push(json);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
cpalc--; //remove audio/dynamically generated palettes
|
cpalc--; //remove audio/dynamically generated palettes
|
||||||
console.error(`Error fetching JSON from ${url}: `, error);
|
console.error(`Error fetching JSON from ${url}: `, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//If there is room for more custom palettes, add an empty, gray slot
|
//If there is room for more custom palettes, add an empty, gray slot
|
||||||
if (paletteArray.length < 10) {
|
if (palArr.length < cpalm) {
|
||||||
//Room for one more :)
|
//Room for one more :)
|
||||||
paletteArray.push({"palette":[0,70,70,70,255,70,70,70]});
|
palArr.push({"palette":[0,70,70,70,255,70,70,70]});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get static palettes from localStorage and do some magic to reformat them into the same format as the palette JSONs
|
//Get static palettes from localStorage and do some magic to reformat them into the same format as the palette JSONs
|
||||||
@@ -569,12 +466,12 @@
|
|||||||
|
|
||||||
const wledPalx = JSON.parse(localStorage.getItem('wledPalx'));
|
const wledPalx = JSON.parse(localStorage.getItem('wledPalx'));
|
||||||
if (!wledPalx) {
|
if (!wledPalx) {
|
||||||
alert("The cache of palettes are missig from your browser. You should probably return to the main page and let it load properly for the palettes cache to regenerate before returning here.","Missing cached palettes!")
|
alert("Palette cache missing from browser. Return to main page first.","Missing cache!")
|
||||||
} else {
|
} else {
|
||||||
for (const key in wledPalx.p) {
|
for (const key in wledPalx.p) {
|
||||||
wledPalx.p[key].name = paletteName[key];
|
wledPalx.p[key].name = palNm[key];
|
||||||
if (key > 245) {
|
if (key > 255-cpalm) {
|
||||||
delete wledPalx.p[key];
|
delete wledPalx.p[key]; // remove custom palettes
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const arr = wledPalx.p[key];
|
const arr = wledPalx.p[key];
|
||||||
@@ -610,130 +507,133 @@
|
|||||||
// Sort pArray by name
|
// Sort pArray by name
|
||||||
pArray.sort((a, b) => a.name.localeCompare(b.name));
|
pArray.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
|
||||||
paletteArray.push( ...pArray);
|
palArr.push( ...pArray);
|
||||||
}
|
}
|
||||||
generatePaletteDivs();
|
genPalDivs();
|
||||||
}
|
}
|
||||||
|
|
||||||
function generatePaletteDivs() {
|
function genPalDivs() {
|
||||||
const palettesDiv = gId("palettes");
|
const palsDiv = gId("pals");
|
||||||
const staticPalettesDiv = gId("staticPalettes");
|
const sPalsDiv = gId("sPals");
|
||||||
const paletteDivs = Array.from(palettesDiv.children).filter((child) => {
|
const memWarn = gId("memWarn");
|
||||||
return child.id.match(/^palette\d$/); // match only elements with id starting with "palette" followed by a single digit
|
const palDivs = Array.from(palsDiv.children).filter((child) => {
|
||||||
|
return /^pal\d+$/.test(child.id); // match ids "pal" followed by one or more digits
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const div of paletteDivs) {
|
for (const div of palDivs) {
|
||||||
palettesDiv.removeChild(div); // remove each div that matches the above selector
|
palsDiv.removeChild(div); // remove each div that matches the above selector
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < paletteArray.length; i++) {
|
memWarn.style.display = (cpalc >= 10) ? 'block' : 'none'; // Show/hide memory warning based on custom palette count
|
||||||
const palette = paletteArray[i];
|
|
||||||
const paletteDiv = cE("div");
|
|
||||||
paletteDiv.id = `palette${i}`;
|
|
||||||
paletteDiv.classList.add("palette");
|
|
||||||
const thisKey = Object.keys(palette)[0];
|
|
||||||
paletteDiv.dataset.colarray = JSON.stringify(palette[thisKey]);
|
|
||||||
|
|
||||||
const gradientDiv = cE("div");
|
for (let i = 0; i < palArr.length; i++) {
|
||||||
gradientDiv.id = `paletteGradient${i}`
|
const pal = palArr[i];
|
||||||
const buttonsDiv = cE("div");
|
const palDiv = cE("div");
|
||||||
buttonsDiv.id = `buttonsDiv${i}`;
|
palDiv.id = `pal${i}`;
|
||||||
buttonsDiv.classList.add("buttonsDiv")
|
palDiv.classList.add("pal");
|
||||||
|
const thisKey = Object.keys(pal)[0];
|
||||||
|
palDiv.dataset.colarray = JSON.stringify(pal[thisKey]);
|
||||||
|
|
||||||
const sendSpan = cE("span");
|
const gradDiv = cE("div");
|
||||||
sendSpan.id = `sendSpan${i}`;
|
gradDiv.id = `pGrad${i}`
|
||||||
sendSpan.onclick = function() {initiateUpload(i)};
|
const btnsDiv = cE("div");
|
||||||
sendSpan.setAttribute('title', `Send current editor to slot ${i}`); // perhaps Save instead of Send?
|
btnsDiv.id = `btns${i}`;
|
||||||
sendSpan.innerHTML = svgSave;
|
btnsDiv.classList.add("btnsDiv")
|
||||||
sendSpan.classList.add("sendSpan")
|
|
||||||
const editSpan = cE("span");
|
const sSpan = cE("span");
|
||||||
editSpan.id = `editSpan${i}`;
|
sSpan.id = `s${i}`;
|
||||||
editSpan.onclick = function() {loadForEdit(i)};
|
sSpan.onclick = function() {initUpload(i)};
|
||||||
editSpan.setAttribute('title', `Copy slot ${i} palette to editor`);
|
sSpan.setAttribute('title', `Send current editor to slot ${i}`); // perhaps Save instead of Send?
|
||||||
if (paletteArray[i].name) {
|
sSpan.innerHTML = svgSave;
|
||||||
editSpan.setAttribute('title', `Copy ${paletteArray[i].name} palette to editor`);
|
sSpan.classList.add("sSpan")
|
||||||
|
const eSpan = cE("span");
|
||||||
|
eSpan.id = `e${i}`;
|
||||||
|
eSpan.onclick = function() {loadEdit(i)};
|
||||||
|
eSpan.setAttribute('title', `Copy slot ${i} to editor`);
|
||||||
|
if (palArr[i].name) {
|
||||||
|
eSpan.setAttribute('title', `Copy ${palArr[i].name} to editor`);
|
||||||
}
|
}
|
||||||
editSpan.innerHTML = svgEdit;
|
eSpan.innerHTML = svgEdit;
|
||||||
editSpan.classList.add("editSpan")
|
eSpan.classList.add("eSpan")
|
||||||
|
|
||||||
gradientDiv.classList.add("paletteGradients");
|
gradDiv.classList.add("pGrads");
|
||||||
let gradientColors = "";
|
let gCols = "";
|
||||||
|
|
||||||
for (let j = 0; j < palette[thisKey].length; j += 2) {
|
for (let j = 0; j < pal[thisKey].length; j += 2) {
|
||||||
const position = palette[thisKey][j];
|
const pos = pal[thisKey][j];
|
||||||
if (typeof(palette[thisKey][j+1]) === "string") {
|
if (typeof(pal[thisKey][j+1]) === "string") {
|
||||||
gradientColors += `#${palette[thisKey][j+1]} ${position/255*100}%, `;
|
gCols += `#${pal[thisKey][j+1]} ${pos/255*100}%, `;
|
||||||
} else {
|
} else {
|
||||||
const red = palette[thisKey][j + 1];
|
const r = pal[thisKey][j + 1];
|
||||||
const green = palette[thisKey][j + 2];
|
const g = pal[thisKey][j + 2];
|
||||||
const blue = palette[thisKey][j + 3];
|
const b = pal[thisKey][j + 3];
|
||||||
gradientColors += `rgba(${red}, ${green}, ${blue}, 1) ${position/255*100}%, `;
|
gCols += `rgba(${r}, ${g}, ${b}, 1) ${pos/255*100}%, `;
|
||||||
j += 2;
|
j += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gradientColors = gradientColors.slice(0, -2); // remove the last comma and space
|
gCols = gCols.slice(0, -2); // remove the last comma and space
|
||||||
gradientDiv.style.backgroundImage = `linear-gradient(to right, ${gradientColors})`;
|
gradDiv.style.backgroundImage = `linear-gradient(to right, ${gCols})`;
|
||||||
paletteDiv.className = "palGradientParent";
|
palDiv.className = "pGradPar";
|
||||||
if (thisKey == "palette") {
|
if (thisKey == "palette") {
|
||||||
buttonsDiv.appendChild(sendSpan); //Only offer to send to custom palettes
|
btnsDiv.appendChild(sSpan); //Only offer to send to custom palettes
|
||||||
} else{
|
} else{
|
||||||
editSpan.style.marginLeft = "25px";
|
eSpan.style.marginLeft = "25px";
|
||||||
}
|
}
|
||||||
if (i!=cpalc) {
|
if (i!=cpalc) {
|
||||||
buttonsDiv.appendChild(editSpan); //Dont offer to edit the empty spot
|
btnsDiv.appendChild(eSpan); //Dont offer to edit the empty spot
|
||||||
}
|
}
|
||||||
paletteDiv.appendChild(gradientDiv);
|
palDiv.appendChild(gradDiv);
|
||||||
paletteDiv.appendChild(buttonsDiv);
|
palDiv.appendChild(btnsDiv);
|
||||||
if (thisKey == "palette") {
|
if (thisKey == "palette") {
|
||||||
palettesDiv.appendChild(paletteDiv);
|
palsDiv.appendChild(palDiv);
|
||||||
} else {
|
} else {
|
||||||
staticPalettesDiv.appendChild(paletteDiv);
|
sPalsDiv.appendChild(palDiv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadForEdit(i) {
|
function loadEdit(i) {
|
||||||
d.querySelectorAll('input[id^="colorPicker"]').forEach((input) => {
|
d.querySelectorAll('input[id^="cPick"]').forEach((input) => {
|
||||||
input.parentNode.removeChild(input);
|
input.parentNode.removeChild(input);
|
||||||
});
|
});
|
||||||
d.querySelectorAll('span[id^="colorMarker"], span[id^="colorPickerMarker"], span[id^="deleteMarker"]').forEach((span) => {
|
d.querySelectorAll('span[id^="cMark"], span[id^="cPM"], span[id^="dMark"]').forEach((span) => {
|
||||||
span.parentNode.removeChild(span);
|
span.parentNode.removeChild(span);
|
||||||
});
|
});
|
||||||
|
|
||||||
let colArray = JSON.parse(gId(`palette${i}`).getAttribute("data-colarray"));
|
let colArr = JSON.parse(gId(`pal${i}`).getAttribute("data-colarray"));
|
||||||
|
|
||||||
for (let j = 0; j < colArray.length; j += 2) {
|
for (let j = 0; j < colArr.length; j += 2) {
|
||||||
const position = colArray[j];
|
const pos = colArr[j];
|
||||||
let hex;
|
let hex;
|
||||||
if (typeof(colArray[j+1]) === "string") {
|
if (typeof(colArr[j+1]) === "string") {
|
||||||
hex = `#${colArray[j+1]}`;
|
hex = `#${colArr[j+1]}`;
|
||||||
} else {
|
} else {
|
||||||
const red = colArray[j + 1];
|
const r = colArr[j + 1];
|
||||||
const green = colArray[j + 2];
|
const g = colArr[j + 2];
|
||||||
const blue = colArray[j + 3];
|
const b = colArr[j + 3];
|
||||||
hex = rgbToHex(red, green, blue);
|
hex = rgbToHex(r, g, b);
|
||||||
j += 2;
|
j += 2;
|
||||||
}
|
}
|
||||||
addC(position, hex);
|
addC(pos, hex);
|
||||||
window.scroll(0, 0);
|
window.scroll(0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function distribute() {
|
function distrib() {
|
||||||
let colorMarkers = [...gradientBox.querySelectorAll('.color-marker')];
|
let cMarks = [...gBox.querySelectorAll('.cMark')];
|
||||||
colorMarkers.sort((a, b) => a.getAttribute('data-truepos') - b.getAttribute('data-truepos'));
|
cMarks.sort((a, b) => a.getAttribute('data-tpos') - b.getAttribute('data-tpos'));
|
||||||
colorMarkers = colorMarkers.slice(1, -1);
|
cMarks = cMarks.slice(1, -1);
|
||||||
const spacing = Math.round(256 / (colorMarkers.length + 1));
|
const spacing = Math.round(256 / (cMarks.length + 1));
|
||||||
|
|
||||||
colorMarkers.forEach((e, i) => {
|
cMarks.forEach((e, i) => {
|
||||||
const markerId = e.id.match(/\d+/)[0];
|
const mId = e.id.match(/\d+/)[0];
|
||||||
const trueCol = e.getAttribute("data-truecol");
|
const tCol = e.getAttribute("data-tcol");
|
||||||
gradientBox.removeChild(e);
|
gBox.removeChild(e);
|
||||||
gradientBox.removeChild(gId(`colorPicker${markerId}`));
|
gBox.removeChild(gId(`cPick${mId}`));
|
||||||
gradientBox.removeChild(gId(`colorPickerMarker${markerId}`));
|
gBox.removeChild(gId(`cPM${mId}`));
|
||||||
gradientBox.removeChild(gId(`deleteMarker${markerId}`));
|
gBox.removeChild(gId(`dMark${mId}`));
|
||||||
addC(spacing * (i + 1), trueCol);
|
addC(spacing * (i + 1), tCol);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1042,8 +1042,7 @@ function genPalPrevCss(id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
var gradient = [];
|
var gradient = [];
|
||||||
for (let j = 0; j < paletteData.length; j++) {
|
paletteData.forEach((e,j) => {
|
||||||
const e = paletteData[j];
|
|
||||||
let r, g, b;
|
let r, g, b;
|
||||||
let index = false;
|
let index = false;
|
||||||
if (Array.isArray(e)) {
|
if (Array.isArray(e)) {
|
||||||
@@ -1065,9 +1064,8 @@ function genPalPrevCss(id)
|
|||||||
if (index === false) {
|
if (index === false) {
|
||||||
index = Math.round(j / paletteData.length * 100);
|
index = Math.round(j / paletteData.length * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
gradient.push(`rgb(${r},${g},${b}) ${index}%`);
|
gradient.push(`rgb(${r},${g},${b}) ${index}%`);
|
||||||
}
|
});
|
||||||
|
|
||||||
return `background: linear-gradient(to right,${gradient.join()});`;
|
return `background: linear-gradient(to right,${gradient.join()});`;
|
||||||
}
|
}
|
||||||
@@ -3088,11 +3086,9 @@ function unify(e) { return e.changedTouches ? e.changedTouches[0] : e; }
|
|||||||
|
|
||||||
function hasIroClass(classList)
|
function hasIroClass(classList)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < classList.length; i++) {
|
let found = false;
|
||||||
var element = classList[i];
|
classList.forEach((e)=>{ if (e.startsWith('Iro')) found = true; });
|
||||||
if (element.startsWith('Iro')) return true;
|
return found;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
//required by rangetouch.js
|
//required by rangetouch.js
|
||||||
function lock(e)
|
function lock(e)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||||
<title>WLED Settings</title>
|
<title>WLED Settings</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
function S() {
|
function S() {
|
||||||
getLoc();
|
getLoc();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||||
<title>2D Set-up</title>
|
<title>2D Set-up</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
var maxPanels=64;
|
var maxPanels=64;
|
||||||
var ctx = null;
|
var ctx = null;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>DMX Settings</title>
|
<title>DMX Settings</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
function HW(){window.open("https://kno.wled.ge/interfaces/dmx-output/");}
|
function HW(){window.open("https://kno.wled.ge/interfaces/dmx-output/");}
|
||||||
function GCH(num) {
|
function GCH(num) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||||
<title>LED Settings</title>
|
<title>LED Settings</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
var maxB=1,maxD=1,maxA=1,maxV=0,maxM=4000,maxPB=2048,maxL=1664,maxCO=5; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
var maxB=1,maxD=1,maxA=1,maxV=0,maxM=4000,maxPB=2048,maxL=1664,maxCO=5; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
||||||
var customStarts=false,startsDirty=[];
|
var customStarts=false,startsDirty=[];
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Misc Settings</title>
|
<title>Misc Settings</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
function U() { window.open(getURL("/update"),"_self"); }
|
function U() { window.open(getURL("/update"),"_self"); }
|
||||||
function checkNum(o) {
|
function checkNum(o) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Sync Settings</title>
|
<title>Sync Settings</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
|
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
|
||||||
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
|
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Time Settings</title>
|
<title>Time Settings</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
var el=false;
|
var el=false;
|
||||||
var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||||
<title>UI Settings</title>
|
<title>UI Settings</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
var initial_ds, initial_st, initial_su, oldUrl;
|
var initial_ds, initial_st, initial_su, oldUrl;
|
||||||
var sett = null;
|
var sett = null;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||||
<title>Usermod Settings</title>
|
<title>Usermod Settings</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
var umCfg = {};
|
var umCfg = {};
|
||||||
var pins = [], pinO = [], owner;
|
var pins = [], pinO = [], owner;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||||
<title>WiFi Settings</title>
|
<title>WiFi Settings</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
var scanLoops = 0, preScanSSID = "";
|
var scanLoops = 0, preScanSSID = "";
|
||||||
var maxNetworks = 3;
|
var maxNetworks = 3;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta content='width=device-width' name='viewport'>
|
<meta content='width=device-width' name='viewport'>
|
||||||
<title>WLED Update</title>
|
<title>WLED Update</title>
|
||||||
<script src="common.js" async type="text/javascript"></script>
|
<script src="common.js" type="text/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
function B() { window.history.back(); }
|
function B() { window.history.back(); }
|
||||||
var cnfr = false;
|
var cnfr = false;
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
|
||||||
#include "palettes.h"
|
|
||||||
|
|
||||||
#define JSON_PATH_STATE 1
|
#define JSON_PATH_STATE 1
|
||||||
#define JSON_PATH_INFO 2
|
#define JSON_PATH_INFO 2
|
||||||
#define JSON_PATH_STATE_INFO 3
|
#define JSON_PATH_STATE_INFO 3
|
||||||
@@ -771,7 +769,8 @@ void serializeInfo(JsonObject root)
|
|||||||
|
|
||||||
root[F("fxcount")] = strip.getModeCount();
|
root[F("fxcount")] = strip.getModeCount();
|
||||||
root[F("palcount")] = getPaletteCount();
|
root[F("palcount")] = getPaletteCount();
|
||||||
root[F("cpalcount")] = customPalettes.size(); //number of custom palettes
|
root[F("cpalcount")] = customPalettes.size(); // number of custom palettes
|
||||||
|
root[F("cpalmax")] = WLED_MAX_CUSTOM_PALETTES; // maximum number of custom palettes
|
||||||
|
|
||||||
JsonArray ledmaps = root.createNestedArray(F("maps"));
|
JsonArray ledmaps = root.createNestedArray(F("maps"));
|
||||||
for (size_t i=0; i<WLED_MAX_LEDMAPS; i++) {
|
for (size_t i=0; i<WLED_MAX_LEDMAPS; i++) {
|
||||||
@@ -935,7 +934,7 @@ void serializePalettes(JsonObject root, int page)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int customPalettesCount = customPalettes.size();
|
int customPalettesCount = customPalettes.size();
|
||||||
int palettesCount = getPaletteCount() - customPalettesCount;
|
int palettesCount = getPaletteCount() - customPalettesCount; // palettesCount is number of palettes, not palette index
|
||||||
|
|
||||||
int maxPage = (palettesCount + customPalettesCount -1) / itemPerPage;
|
int maxPage = (palettesCount + customPalettesCount -1) / itemPerPage;
|
||||||
if (page > maxPage) page = maxPage;
|
if (page > maxPage) page = maxPage;
|
||||||
@@ -947,8 +946,8 @@ void serializePalettes(JsonObject root, int page)
|
|||||||
root[F("m")] = maxPage; // inform caller how many pages there are
|
root[F("m")] = maxPage; // inform caller how many pages there are
|
||||||
JsonObject palettes = root.createNestedObject("p");
|
JsonObject palettes = root.createNestedObject("p");
|
||||||
|
|
||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i <= end; i++) {
|
||||||
JsonArray curPalette = palettes.createNestedArray(String(i>=palettesCount ? 255 - i + palettesCount : i));
|
JsonArray curPalette = palettes.createNestedArray(String(i<=palettesCount ? i : 255 - (i - (palettesCount + 1))));
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0: //default palette
|
case 0: //default palette
|
||||||
setPaletteColors(curPalette, PartyColors_p);
|
setPaletteColors(curPalette, PartyColors_p);
|
||||||
@@ -977,8 +976,8 @@ void serializePalettes(JsonObject root, int page)
|
|||||||
curPalette.add("c1");
|
curPalette.add("c1");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (i >= palettesCount)
|
if (i > palettesCount)
|
||||||
setPaletteColors(curPalette, customPalettes[i - palettesCount]);
|
setPaletteColors(curPalette, customPalettes[i - (palettesCount + 1)]);
|
||||||
else if (i < 13) // palette 6 - 12, fastled palettes
|
else if (i < 13) // palette 6 - 12, fastled palettes
|
||||||
setPaletteColors(curPalette, *fastledPalettes[i-6]);
|
setPaletteColors(curPalette, *fastledPalettes[i-6]);
|
||||||
else {
|
else {
|
||||||
|
|||||||
5
wled00/palettes.h → wled00/palettes.cpp
Executable file → Normal file
5
wled00/palettes.h → wled00/palettes.cpp
Executable file → Normal file
@@ -1,5 +1,4 @@
|
|||||||
#ifndef PalettesWLED_h
|
#include "wled.h"
|
||||||
#define PalettesWLED_h
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WLED Color palettes
|
* WLED Color palettes
|
||||||
@@ -768,5 +767,3 @@ const uint8_t* const gGradientPalettes[] PROGMEM = {
|
|||||||
candy2_gp, //70-57 Candy2
|
candy2_gp, //70-57 Candy2
|
||||||
trafficlight_gp //71-58 Traffic Light
|
trafficlight_gp //71-58 Traffic Light
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -230,7 +230,7 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
|
|||||||
} else return 0;
|
} else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src == JSON_palette_names && mode > (GRADIENT_PALETTE_COUNT + 13)) {
|
if (src == JSON_palette_names && mode > 255-customPalettes.size()) {
|
||||||
snprintf_P(dest, maxLen, PSTR("~ Custom %d ~"), 255-mode);
|
snprintf_P(dest, maxLen, PSTR("~ Custom %d ~"), 255-mode);
|
||||||
dest[maxLen-1] = '\0';
|
dest[maxLen-1] = '\0';
|
||||||
return strlen(dest);
|
return strlen(dest);
|
||||||
|
|||||||
@@ -475,29 +475,31 @@ void initServer()
|
|||||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
if (captivePortal(request)) return;
|
if (captivePortal(request)) return;
|
||||||
if (!showWelcomePage || request->hasArg(F("sliders"))) {
|
if (!showWelcomePage || request->hasArg(F("sliders"))) {
|
||||||
handleStaticContent(request, F("/index.htm"), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_index, PAGE_index_L);
|
handleStaticContent(request, F("/index.htm"), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_index, PAGE_index_length);
|
||||||
} else {
|
} else {
|
||||||
serveSettings(request);
|
serveSettings(request);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_PIXART
|
#ifndef WLED_DISABLE_2D
|
||||||
|
#ifdef WLED_ENABLE_PIXART
|
||||||
static const char _pixart_htm[] PROGMEM = "/pixart.htm";
|
static const char _pixart_htm[] PROGMEM = "/pixart.htm";
|
||||||
server.on(_pixart_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on(_pixart_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStaticContent(request, FPSTR(_pixart_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_pixart, PAGE_pixart_L);
|
handleStaticContent(request, FPSTR(_pixart_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_pixart, PAGE_pixart_length);
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_PXMAGIC
|
#ifndef WLED_DISABLE_PXMAGIC
|
||||||
static const char _pxmagic_htm[] PROGMEM = "/pxmagic.htm";
|
static const char _pxmagic_htm[] PROGMEM = "/pxmagic.htm";
|
||||||
server.on(_pxmagic_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on(_pxmagic_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStaticContent(request, FPSTR(_pxmagic_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_pxmagic, PAGE_pxmagic_L);
|
handleStaticContent(request, FPSTR(_pxmagic_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_pxmagic, PAGE_pxmagic_length);
|
||||||
});
|
});
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char _cpal_htm[] PROGMEM = "/cpal.htm";
|
static const char _cpal_htm[] PROGMEM = "/cpal.htm";
|
||||||
server.on(_cpal_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on(_cpal_htm, HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
handleStaticContent(request, FPSTR(_cpal_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_cpal, PAGE_cpal_L);
|
handleStaticContent(request, FPSTR(_cpal_htm), 200, FPSTR(CONTENT_TYPE_HTML), PAGE_cpal, PAGE_cpal_length);
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_WEBSOCKETS
|
#ifdef WLED_ENABLE_WEBSOCKETS
|
||||||
|
|||||||
Reference in New Issue
Block a user