From eda70df23b6410a4ef4a19df22e457d35ae21e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Thu, 11 Sep 2025 17:34:15 +0200 Subject: [PATCH 1/8] Variable custom palettes and tuning - add TRANSPARENT() marco for uint32_t color conversion - allow more than 10 custom palettes via WLED_MAX_CUSTOM_PALETTES - add setColor(CRGBA) method - move palettes into CPP file - tune index.js --- wled00/FX.h | 2 ++ wled00/FX_2Dfcn.cpp | 1 - wled00/FX_fcn.cpp | 17 ++++++++++------- wled00/colors.cpp | 2 +- wled00/colors.h | 6 +++++- wled00/const.h | 8 +++++++- wled00/data/cpal/cpal.htm | 2 +- wled00/data/index.js | 14 +++++--------- wled00/json.cpp | 2 -- wled00/{palettes.h => palettes.cpp} | 5 +---- wled00/util.cpp | 2 +- 11 files changed, 33 insertions(+), 28 deletions(-) rename wled00/{palettes.h => palettes.cpp} (99%) mode change 100755 => 100644 diff --git a/wled00/FX.h b/wled00/FX.h index 097c857caf..dbad4334cd 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -137,6 +137,7 @@ extern byte realtimeMode; // used in getMappedPixelIndex() #define ULTRAWHITE (uint32_t)0xFFFFFFFF #define DARKSLATEGRAY (uint32_t)0x2F4F4F #define DARKSLATEGREY DARKSLATEGRAY +#define TRANSPARENT(a) CRGBA(a).setOpacity(0) // segment options #define NO_OPTIONS (uint16_t)0x0000 @@ -660,6 +661,7 @@ class Segment { void beginDraw(uint16_t prog = 0xFFFFU); // set up parameters for current effect void setGeometry(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1, uint8_t m12=0); Segment &setColor(uint8_t slot, uint32_t c); + Segment &setColor(uint8_t slot, CRGBA c); Segment &setCCT(uint16_t k); Segment &setOpacity(uint8_t o); Segment &setOption(uint8_t n, bool val); diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 9a3c6fbe81..c8c949edb3 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -8,7 +8,6 @@ Parts of the code adapted from WLED Sound Reactive */ #include "wled.h" -#include "palettes.h" // setUpMatrix() - constructs ledmap array from matrix of panels with WxH pixels // this converts physical (possibly irregular) LED arrangement into well defined diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 2f8d5515fd..5afa37ada5 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -11,7 +11,6 @@ */ #include "wled.h" #include "FXparticleSystem.h" // TODO: better define the required function (mem service) in FX.h? -#include "palettes.h" /* Custom per-LED mapping has moved! @@ -219,8 +218,12 @@ void Segment::resetIfRequired() { } CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) { - if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; - if (pal > 245 && (customPalettes.size() == 0 || 255U-pal > customPalettes.size()-1)) pal = 0; + // there is one randomy generated palette (1) followed by 4 palettes created from segment colors (2-5) + // 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()+1) pal = 0; // out of bounds palette //default palette. Differs depending on effect if (pal == 0) pal = _default_palette; // _default_palette is set in setMode() switch (pal) { @@ -256,13 +259,13 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) { } break;} default: //progmem palettes - if (pal>245) { + if (pal > 255 - customPalettes.size()) { targetPalette = customPalettes[255-pal]; // we checked bounds above - } else if (pal < 13) { // palette 6 - 12, fastled palettes - targetPalette = *fastledPalettes[pal-6]; + } else if (pal < DYNAMIC_PALETTE_COUNT+FASTLED_PALETTE_COUNT+1) { // palette 6 - 12, fastled palettes + targetPalette = *fastledPalettes[pal-DYNAMIC_PALETTE_COUNT-1]; } else { 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); } break; diff --git a/wled00/colors.cpp b/wled00/colors.cpp index bf2b69d73a..f848787f0c 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -252,7 +252,7 @@ void loadCustomPalettes() { byte tcp[72]; //support gradient palettes with up to 18 entries CRGBPalette16 targetPalette; customPalettes.clear(); // start fresh - for (int index = 0; index<10; index++) { + for (int index = 0; index < WLED_MAX_CUSTOM_PALETTES; index++) { char fileName[32]; sprintf_P(fileName, PSTR("/palette%d.json"), index); diff --git a/wled00/colors.h b/wled00/colors.h index 376959fd65..8ee1cf4f4e 100644 --- a/wled00/colors.h +++ b/wled00/colors.h @@ -123,7 +123,7 @@ CRGBPalette16 generateHarmonicRandomPalette(const CRGBPalette16 &basepalette); CRGBPalette16 generateRandomPalette(); void loadCustomPalettes(); extern std::vector 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]))); } void hsv2rgb(const CHSV32& hsv, uint32_t& 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); +// palettes +extern const TProgmemRGBPalette16* const fastledPalettes[]; +extern const uint8_t* const gGradientPalettes[]; #endif + diff --git a/wled00/const.h b/wled00/const.h index 1abf245396..f1ea77788a 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -6,7 +6,13 @@ * 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 WLED_MAX_CUSTOM_PALETTES + #define WLED_MAX_CUSTOM_PALETTES 10 +#endif // You can define custom product info from build flags. // This is useful to allow API consumer to identify what type of WLED version diff --git a/wled00/data/cpal/cpal.htm b/wled00/data/cpal/cpal.htm index 8fa715bc8d..aa38bc8cb6 100644 --- a/wled00/data/cpal/cpal.htm +++ b/wled00/data/cpal/cpal.htm @@ -557,7 +557,7 @@

} } //If there is room for more custom palettes, add an empty, gray slot - if (paletteArray.length < 10) { + if (paletteArray.length < 10) { // TODO: use WLED_MAX_CUSTOM_PALETTES //Room for one more :) paletteArray.push({"palette":[0,70,70,70,255,70,70,70]}); } diff --git a/wled00/data/index.js b/wled00/data/index.js index fe154783d0..2514f03fb1 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -1042,8 +1042,7 @@ function genPalPrevCss(id) } var gradient = []; - for (let j = 0; j < paletteData.length; j++) { - const e = paletteData[j]; + paletteData.forEach((e,j) => { let r, g, b; let index = false; if (Array.isArray(e)) { @@ -1065,9 +1064,8 @@ function genPalPrevCss(id) if (index === false) { index = Math.round(j / paletteData.length * 100); } - gradient.push(`rgb(${r},${g},${b}) ${index}%`); - } + }); 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) { - for (var i = 0; i < classList.length; i++) { - var element = classList[i]; - if (element.startsWith('Iro')) return true; - } - return false; + let found = false; + classList.forEach((e)=>{ if (e.startsWith('Iro')) found = true; }); + return found; } //required by rangetouch.js function lock(e) diff --git a/wled00/json.cpp b/wled00/json.cpp index e8ebaaba29..e812e8b464 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -1,7 +1,5 @@ #include "wled.h" -#include "palettes.h" - #define JSON_PATH_STATE 1 #define JSON_PATH_INFO 2 #define JSON_PATH_STATE_INFO 3 diff --git a/wled00/palettes.h b/wled00/palettes.cpp old mode 100755 new mode 100644 similarity index 99% rename from wled00/palettes.h rename to wled00/palettes.cpp index a77540fd1f..4781ffc1cc --- a/wled00/palettes.h +++ b/wled00/palettes.cpp @@ -1,5 +1,4 @@ -#ifndef PalettesWLED_h -#define PalettesWLED_h +#include "wled.h" /* * WLED Color palettes @@ -768,5 +767,3 @@ const uint8_t* const gGradientPalettes[] PROGMEM = { candy2_gp, //70-57 Candy2 trafficlight_gp //71-58 Traffic Light }; - -#endif diff --git a/wled00/util.cpp b/wled00/util.cpp index 8299904d5f..1f3573be74 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -230,7 +230,7 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe } 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); dest[maxLen-1] = '\0'; return strlen(dest); From a6d01ede971949eeff5850b3e8d9aef5a795eb05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Fri, 12 Sep 2025 08:41:43 +0200 Subject: [PATCH 2/8] Add maximum custom palettes info --- wled00/FX_fcn.cpp | 3 +-- wled00/data/cpal/cpal.htm | 38 ++++++++++++++++++-------------------- wled00/json.cpp | 3 ++- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 5afa37ada5..51d0b985ee 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -569,8 +569,7 @@ Segment &Segment::setMode(uint8_t fx, bool loadDefaults) { } Segment &Segment::setPalette(uint8_t pal) { - if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0; // built in palettes - if (pal > 245 && (customPalettes.size() == 0 || 255U-pal > customPalettes.size()-1)) pal = 0; // custom palettes + if (pal <= 255-customPalettes.size() && pal > FIXED_PALETTE_COUNT) pal = 0; // not built in palette or custom palette if (pal != palette) { //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) diff --git a/wled00/data/cpal/cpal.htm b/wled00/data/cpal/cpal.htm index aa38bc8cb6..4e1b37ed3e 100644 --- a/wled00/data/cpal/cpal.htm +++ b/wled00/data/cpal/cpal.htm @@ -11,6 +11,7 @@ function gId(e) {return d.getElementById(e);} function cE(e) {return d.createElement(e);} +

- - - - - + + + + + - WLED Custom Palette Editor + WLED Palette Editor

-
-
-
+
-
-
-
- Currently in use custom palettes -
+
+
+ +
Custom palettes
-
- 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. -
+
Click gradient to add. Box = color. Red = delete. Arrow = upload. Pencil = edit.
-
-
- Available static palettes -
+
+
Static palettes
- + + + + + + + + + + +