diff --git a/usermods/customeffects/customeffects.css b/usermods/customeffects/customeffects.css new file mode 100644 index 00000000..39ef3967 --- /dev/null +++ b/usermods/customeffects/customeffects.css @@ -0,0 +1,12 @@ +.ceTextarea { + width: 90%; + height: 300px; + resize: none; + white-space: pre; +} + +#kceEditor { + max-width: 490px; + display: inline-block; +} + diff --git a/usermods/customeffects/customeffects.js b/usermods/customeffects/customeffects.js new file mode 100644 index 00000000..78d7cf79 --- /dev/null +++ b/usermods/customeffects/customeffects.js @@ -0,0 +1,154 @@ + +var isCEEditor = false; + +function toggleCEEditor(name, segID) { + if (isInfo) toggleInfo(); + if (isNodes) toggleNodes(); + isCEEditor = !isCEEditor; + if (isCEEditor) populateCEEditor(name, segID); + d.getElementById('ceEditor').style.transform = (isCEEditor) ? "translateY(0px)":"translateY(100%)"; +} + +function fetchAndExecute(url, name, callback) +{ + fetch + (url+name, { + method: 'get' + }) + .then(res => { + if (!res.ok) { + showToast("File " + name + " not found", true); + return ""; + } + return res.text(); + }) + .then(text => { + callback(text); + }) + .catch(function (error) { + showToast("Error getting " + name, true); + // showToast(error, true); + // console.log(error); + presetError(false); + }) + .finally(() => { + // if (callback) setTimeout(callback,99); + }); +} + +function loadLogFile(name, attempt) { + var ceLogArea = d.getElementById("ceLogArea"); + fetchAndExecute((loc?`http://${locip}`:'.') + "/", name , function(logtext) + { + if (logtext == "") { + if (attempt < 10) { + ceLogArea.value = ("...........").substring(0, attempt + 1); + setTimeout(() => + { + loadLogFile(name, attempt + 1); + }, 1000); + } + else + ceLogArea.value = "log not found after 10 seconds"; + } + else + ceLogArea.value = logtext; + }); +} + +function saveCE(name, segID) { + showToast("Saving " + name); + + var ceProgramArea = d.getElementById("ceProgramArea"); + + uploadFileWithText("/" + name, ceProgramArea.value); + + var obj = {"seg": {"id": segID, "reset": true}}; + requestJson(obj); + + var ceLogArea = d.getElementById("ceLogArea"); + ceLogArea.value = "."; + setTimeout(() => + { + loadLogFile(name + ".log", 1); + }, 1000); +} + +function populateCEEditor(name, segID) +{ + fetchAndExecute((loc?`http://${locip}`:'.') + "/", name + ".wled", function(text) + { + var cn=`Custom Effects Editor
+ ${name}.wled
+
+ +
+ +
+ +
+ Custom Effects Library
+ Custom Effects Help
+
Compile and Run Log
+
+ Run log > 3 seconds is send to Serial Ouput.`; + + d.getElementById('kceEditor').innerHTML = cn; + + var ceLogArea = d.getElementById("ceLogArea"); + ceLogArea.value = "."; + loadLogFile(name + ".wled.log", 1); + + }); +} + +function downloadCEFile(name) { + var url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/CustomEffects/wled/"; + + fetchAndExecute(url, name, function(text) { + console.log(text); + if (name == "wled.json" || name == "presets.json") { + if (!confirm('Are you sure to download/overwrite ' + name + '?')) + return; + uploadFileWithText("/" + name, text); + } + else + { + var ceProgramArea = d.getElementById("ceProgramArea"); + ceProgramArea.value = text; + } + }); + + return; + + var request = new XMLHttpRequest(); + request.onload = function() { + if (name == "wled.json" || name == "presets.json") { + if (!confirm('Are you sure to download ' + name + '?')) + return; + uploadFileWithText("/" + name, request.response); + } + else + { + var ceProgramArea = d.getElementById("ceProgramArea"); + ceProgramArea.value = request.response; + } + } + request.open("GET", url); + request.send(); + } + +function loadCETemplate(name) { + var ceProgramArea = d.getElementById("ceProgramArea"); + ceProgramArea.value = `/* + Custom Effects Template + */ + program ${name} + { + function renderFrame() + { + setPixelColor(counter, colorFromPalette(counter, counter)) + } + }`; + +} \ No newline at end of file diff --git a/usermods/customeffects/usermod_v2_customeffects.h b/usermods/customeffects/usermod_v2_customeffects.h index 891b4891..389fa8ac 100644 --- a/usermods/customeffects/usermod_v2_customeffects.h +++ b/usermods/customeffects/usermod_v2_customeffects.h @@ -100,10 +100,16 @@ class CustomEffectsUserMod : public Usermod { unsigned long lastTime = 0; //will be used to download new forecast every hour char errorMessage[100] = ""; + bool enabled = false; + bool initDone = false; + public: void setup() { - strip.addEffect(255, &mode_customEffect, _data_FX_MODE_CUSTOMEFFECT); + if (!initDone) + strip.addEffect(255, &mode_customEffect, _data_FX_MODE_CUSTOMEFFECT); + initDone = true; + enabled = true; } void connected() { @@ -140,6 +146,12 @@ class CustomEffectsUserMod : public Usermod { void addToJsonState(JsonObject& root) { //root["user0"] = userVar0; + if (!initDone) return; // prevent crash on boot applyPreset() + JsonObject usermod = root[FPSTR(_name)]; + if (usermod.isNull()) { + usermod = root.createNestedObject(FPSTR(_name)); + } + usermod["on"] = enabled; } @@ -196,4 +208,4 @@ class CustomEffectsUserMod : public Usermod { }; // strings to reduce flash memory usage (used more than twice) -const char CustomEffectsUserMod::_name[] PROGMEM = "Custom Effects"; +const char CustomEffectsUserMod::_name[] PROGMEM = "CustomEffects"; diff --git a/wled00/data/index.htm b/wled00/data/index.htm index f4b50c44..c9ddeaa3 100644 --- a/wled00/data/index.htm +++ b/wled00/data/index.htm @@ -51,6 +51,7 @@ setTimeout(()=>{h.appendChild(l)},100); + @@ -365,6 +366,11 @@ + + + @@ -380,5 +386,6 @@
+ diff --git a/wled00/data/index.js b/wled00/data/index.js index d9e3c3c6..5fedc024 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -684,7 +684,11 @@ function populateSegments(s) let li = lastinfo; segCount = 0; lowestUnused = 0; lSeg = 0; + console.log(s); + for (var inst of (s.seg||[])) { + console.log(inst); + segCount++; let i = parseInt(inst.id); @@ -728,6 +732,7 @@ function populateSegments(s) `; + let cusEff = `
`; cn += `