Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

**MoonLight bridges the gap between hobbyist lighting projects and professional lighting systems.** Get enterprise-grade performance and flexibility without the enterprise price tag.

- ⚡ **High Performance** - 12K LEDs at 100 FPS with FastLED + parallel drivers
- ⚡ **High Performance** - 12K LEDs at 100 FPS with FastLED + parallel drivers
- 🎨 **3D Effects Engine** - Stunning visuals for 1D strips, 2D panels, 3D cubes, and custom layouts
- 🏗️ **Flexible Setups** - From simple strips to complex installations and DMX fixtures
- 🌐 **Modern IoT** - ESP32-powered with responsive Svelte 5 interface
Expand Down Expand Up @@ -79,7 +79,7 @@ Start creating stunning effects immediately on both mobile and desktop.

| Firmware | Interface |
|----------|-----------|
| 🔧 **ESP-IDF 5** - Modern ESP32 framework | ⚡ **Svelte 5** - Lightning-fast reactive UI |
| 🔧 **ESP-IDF 5** - Modern ESP32 framework | ⚡ **Svelte 5** - Lightning-fast reactive UI |
| 💡 **FastLED 3.10** - Industry-standard LED library | 🎨 **DaisyUI 5** - Modern component library |
| 📡 **PsychicHTTP 1.21** - High-performance web server | 🎯 **Tailwind 4** - Utility-first CSS |
| 📊 **ArduinoJson 7** - Advanced JSON processing | 📱 **Mobile & Desktop** responsive |
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ hide:

**MoonLight bridges the gap between hobbyist lighting projects and professional lighting systems.** Get enterprise-grade performance and flexibility without the enterprise price tag.

- ⚡ **High Performance** - 12K LEDs at 100 FPS with FastLED + parallel drivers
- ⚡️️ **High Performance** - 12K LEDs at 100 FPS with FastLED + parallel drivers
- 🎨 **3D Effects Engine** - Stunning visuals for 1D strips, 2D panels, 3D cubes, and custom layouts
- 🏗️ **Flexible Setups** - From simple strips to complex installations and DMX fixtures
- 🌐 **Modern IoT** - ESP32-powered with responsive Svelte 5 interface
Expand Down Expand Up @@ -85,7 +85,7 @@ Start creating stunning effects immediately on both mobile and desktop.

| Firmware | Interface |
|----------|-----------|
| 🔧 **ESP-IDF 5** - Modern ESP32 framework | ⚡ **Svelte 5** - Lightning-fast reactive UI |
| 🔧 **ESP-IDF 5** - Modern ESP32 framework | ⚡ **Svelte 5** - Lightning-fast reactive UI |
| 💡 **FastLED 3.10** - Industry-standard LED library | 🎨 **DaisyUI 5** - Modern component library |
| 📡 **PsychicHTTP 1.21** - High-performance web server | 🎯 **Tailwind 4** - Utility-first CSS |
| 📊 **ArduinoJson 7** - Advanced JSON processing | 📱 **Mobile & Desktop** responsive |
Expand Down
1 change: 1 addition & 0 deletions docs/moonlight/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ Effects, Modifiers, Layouts and drivers use emoji's to visualize their usage. Se
* 🎨 Using palette
* 🐙 WLED origin
* 💫 MoonLight origin
* ⚡️ FastLED origin
* 🚨 Moving head color effect
* 🗼 Moving head move effect
* 💎 Modifier
Expand Down
6 changes: 3 additions & 3 deletions interface/src/lib/components/moonbase/FieldRenderer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@
{:else if property.type == 'coord3D'}
<input
type="number"
style="width: {String(property.max || 255).length * 2}ch"
style="width: {String(property.max || 255).length + 5}ch"
class="input invalid:border-error invalid:border-2"
min="0"
max="65536"
Expand All @@ -243,7 +243,7 @@
/>
<input
type="number"
style="width: {String(property.max || 255).length * 2}ch"
style="width: {String(property.max || 255).length + 5}ch"
class="input invalid:border-error invalid:border-2"
min="0"
max="65536"
Expand All @@ -252,7 +252,7 @@
/>
<input
type="number"
style="width: {String(property.max || 255).length * 2}ch"
style="width: {String(property.max || 255).length + 5}ch"
class="input invalid:border-error invalid:border-2"
min="0"
max="65536"
Expand Down
25,456 changes: 12,728 additions & 12,728 deletions lib/framework/WWWData.h

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ build_flags =
-D BUILD_TARGET=\"$PIOENV\"
-D APP_NAME=\"MoonLight\" ; 🌙 Must only contain characters from [a-zA-Z0-9-_] as this is converted into a filename
-D APP_VERSION=\"0.6.1\" ; semver compatible version string
-D APP_DATE=\"20251216\" ; 🌙
-D APP_DATE=\"20251217\" ; 🌙

-D PLATFORM_VERSION=\"pioarduino-55.03.34\" ; 🌙 make sure it matches with above plaftform

Expand Down
1 change: 0 additions & 1 deletion src/MoonBase/Nodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ void LiveScriptNode::onLayout() {
LiveScriptNode::~LiveScriptNode() {
EXT_LOGV(ML_TAG, "%s", animation);
scriptRuntime.kill(animation);
Node::~Node();
}

// LiveScriptNode functions
Expand Down
2 changes: 1 addition & 1 deletion src/MoonLight/Layers/PhysicalLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct LightsHeader {
uint8_t offsetRGB3 = UINT8_MAX;
uint8_t offsetBrightness2 = UINT8_MAX; // 31
uint16_t nrOfChannels; // 32, so we can deal with exceptional cases e.g. RGB2040 make sure it starts at even position!!! for alignment!!!
uint8_t lightPreset = UINT8_MAX; // 34, so we can deal with exceptional cases e.g. RGB2040
uint8_t lightPreset = 2; // 34, so we can deal with exceptional cases e.g. RGB2040. default 2 / GRB
// =============
// 35 bytes total
uint8_t fill[5]; // padding to align struct to 40 bytes total. lightsControl will send 37 bytes (prime number)!!! so Monitor.svelte can recognize this
Expand Down
2 changes: 1 addition & 1 deletion src/MoonLight/Layers/VirtualLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ class VirtualLayer {
void addRGB(const Coord3D& position, const CRGB& color) { setRGB(position, getRGB(position) + color); }

void blendColor(const uint16_t indexV, const CRGB& color, uint8_t blendAmount) { setRGB(indexV, blend(color, getRGB(indexV), blendAmount)); }
void blendColor(Coord3D& position, const CRGB& color, const uint8_t blendAmount) { blendColor(XYZ(position), color, blendAmount); }
void blendColor(Coord3D position, const CRGB& color, const uint8_t blendAmount) { blendColor(XYZ(position), color, blendAmount); }

uint8_t getWhite(const uint16_t indexV) { return getLight<uint8_t>(indexV, layerP->lights.header.offsetWhite); }
uint8_t getWhite(Coord3D pos) { return getWhite(XYZ(pos)); }
Expand Down
78 changes: 68 additions & 10 deletions src/MoonLight/Modules/ModuleEffects.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ class ModuleEffects : public NodeManager {
EXT_LOGV(ML_TAG, "");
JsonObject control; // state.data has one or more properties
control = addControl(controls, "layer", "select");
control["default"] = 1;
uint8_t i = 1; //start with 1
control["default"] = 0; // the first entry has index 0 and refers to Layer 1 (layer counting starts with 1)
uint8_t i = 1; // start with 1
for (VirtualLayer* layer : layerP.layers) {
addControlValue(control, i);
i++;
Expand All @@ -78,24 +78,29 @@ class ModuleEffects : public NodeManager {

// MoonLight effects, Solid first then alphabetically
addControlValue(control, getNameAndTags<SolidEffect>());
addControlValue(control, getNameAndTags<AudioRingsEffect>());
addControlValue(control, getNameAndTags<LinesEffect>());
addControlValue(control, getNameAndTags<FireEffect>());
addControlValue(control, getNameAndTags<FixedRectangleEffect>());
addControlValue(control, getNameAndTags<ParticlesEffect>());
addControlValue(control, getNameAndTags<PraxisEffect>());
#if USE_M5UNIFIED
addControlValue(control, getNameAndTags<MoonManEffect>());
#endif
addControlValue(control, getNameAndTags<FreqSawsEffect>());
addControlValue(control, getNameAndTags<RainbowEffect>());
addControlValue(control, getNameAndTags<MarioTestEffect>());
addControlValue(control, getNameAndTags<PixelMapEffect>());
addControlValue(control, getNameAndTags<RandomEffect>());
addControlValue(control, getNameAndTags<RingRandomFlowEffect>());
addControlValue(control, getNameAndTags<RipplesEffect>());
addControlValue(control, getNameAndTags<RubiksCubeEffect>());
addControlValue(control, getNameAndTags<ScrollingTextEffect>());
addControlValue(control, getNameAndTags<SinusEffect>());
addControlValue(control, getNameAndTags<SphereMoveEffect>());
addControlValue(control, getNameAndTags<SpiralFireEffect>());
addControlValue(control, getNameAndTags<StarFieldEffect>());
addControlValue(control, getNameAndTags<VUMeterEffect>());
addControlValue(control, getNameAndTags<WaveEffect>());
addControlValue(control, getNameAndTags<SpiralFireEffect>());

// MoonModules effects, alphabetically
addControlValue(control, getNameAndTags<GameOfLifeEffect>());
Expand All @@ -107,14 +112,29 @@ class ModuleEffects : public NodeManager {
addControlValue(control, getNameAndTags<BouncingBallsEffect>());
addControlValue(control, getNameAndTags<BlurzEffect>());
addControlValue(control, getNameAndTags<DistortionWavesEffect>());
addControlValue(control, getNameAndTags<DJLightEffect>());
addControlValue(control, getNameAndTags<DNAEffect>());
addControlValue(control, getNameAndTags<DripEffect>());
addControlValue(control, getNameAndTags<FreqMatrixEffect>());
addControlValue(control, getNameAndTags<FireworksEffect>());
addControlValue(control, getNameAndTags<FlowEffect>());
addControlValue(control, getNameAndTags<FrizzlesEffect>());
addControlValue(control, getNameAndTags<FunkyPlankEffect>());
addControlValue(control, getNameAndTags<GEQEffect>());
addControlValue(control, getNameAndTags<HeartBeatEffect>());
addControlValue(control, getNameAndTags<LissajousEffect>());
addControlValue(control, getNameAndTags<Noise2DEffect>());
addControlValue(control, getNameAndTags<NoiseMeterEffect>());
addControlValue(control, getNameAndTags<OctopusEffect>());
addControlValue(control, getNameAndTags<PacManEffect>());
addControlValue(control, getNameAndTags<PopCornEffect>());
addControlValue(control, getNameAndTags<RainEffect>());
addControlValue(control, getNameAndTags<TetrixEffect>());
addControlValue(control, getNameAndTags<WaverlyEffect>());

// FastLED effects
addControlValue(control, getNameAndTags<RainbowEffect>());

// Moving head effects, alphabetically
addControlValue(control, getNameAndTags<AmbientMoveEffect>());
addControlValue(control, getNameAndTags<FreqColorsEffect>());
Expand Down Expand Up @@ -151,20 +171,32 @@ class ModuleEffects : public NodeManager {
// MoonLight effects, Solid first then alphabetically
if (equalAZaz09(name, SolidEffect::name()))
node = allocMBObject<SolidEffect>();
else if (equalAZaz09(name, AudioRingsEffect::name()))
node = allocMBObject<AudioRingsEffect>();
else if (equalAZaz09(name, FireEffect::name()))
node = allocMBObject<FireEffect>();
else if (equalAZaz09(name, FixedRectangleEffect::name()))
node = allocMBObject<FixedRectangleEffect>();
else if (equalAZaz09(name, FreqSawsEffect::name()))
node = allocMBObject<FreqSawsEffect>();
else if (equalAZaz09(name, LinesEffect::name()))
node = allocMBObject<LinesEffect>();
else if (equalAZaz09(name, MarioTestEffect::name()))
node = allocMBObject<MarioTestEffect>();
#if USE_M5UNIFIED
else if (equalAZaz09(name, MoonManEffect::name()))
node = allocMBObject<MoonManEffect>();
#endif
else if (equalAZaz09(name, ParticlesEffect::name()))
node = allocMBObject<ParticlesEffect>();
else if (equalAZaz09(name, PraxisEffect::name()))
node = allocMBObject<PraxisEffect>();
else if (equalAZaz09(name, PixelMapEffect::name()))
node = allocMBObject<PixelMapEffect>();
else if (equalAZaz09(name, RandomEffect::name()))
node = allocMBObject<RandomEffect>();
else if (equalAZaz09(name, RingRandomFlowEffect::name()))
node = allocMBObject<RingRandomFlowEffect>();
else if (equalAZaz09(name, RipplesEffect::name()))
node = allocMBObject<RipplesEffect>();
else if (equalAZaz09(name, RubiksCubeEffect::name()))
Expand All @@ -181,6 +213,8 @@ class ModuleEffects : public NodeManager {
node = allocMBObject<WaveEffect>();
else if (equalAZaz09(name, SpiralFireEffect::name()))
node = allocMBObject<SpiralFireEffect>();
else if (equalAZaz09(name, VUMeterEffect::name()))
node = allocMBObject<VUMeterEffect>();

// MoonModules effects, alphabetically
else if (equalAZaz09(name, GameOfLifeEffect::name()))
Expand All @@ -199,25 +233,49 @@ class ModuleEffects : public NodeManager {
node = allocMBObject<BlurzEffect>();
else if (equalAZaz09(name, DistortionWavesEffect::name()))
node = allocMBObject<DistortionWavesEffect>();
else if (equalAZaz09(name, DJLightEffect::name()))
node = allocMBObject<DJLightEffect>();
else if (equalAZaz09(name, DNAEffect::name()))
node = allocMBObject<DNAEffect>();
else if (equalAZaz09(name, DripEffect::name()))
node = allocMBObject<DripEffect>();
else if (equalAZaz09(name, FireworksEffect::name()))
node = allocMBObject<FireworksEffect>();
else if (equalAZaz09(name, FlowEffect::name()))
node = allocMBObject<FlowEffect>();
else if (equalAZaz09(name, FreqMatrixEffect::name()))
node = allocMBObject<FreqMatrixEffect>();
else if (equalAZaz09(name, FrizzlesEffect::name()))
node = allocMBObject<FrizzlesEffect>();
else if (equalAZaz09(name, FunkyPlankEffect::name()))
node = allocMBObject<FunkyPlankEffect>();
else if (equalAZaz09(name, GEQEffect::name()))
node = allocMBObject<GEQEffect>();
else if (equalAZaz09(name, HeartBeatEffect::name()))
node = allocMBObject<HeartBeatEffect>();
else if (equalAZaz09(name, LissajousEffect::name()))
node = allocMBObject<LissajousEffect>();
else if (equalAZaz09(name, Noise2DEffect::name()))
node = allocMBObject<Noise2DEffect>();
else if (equalAZaz09(name, NoiseMeterEffect::name()))
node = allocMBObject<NoiseMeterEffect>();
else if (equalAZaz09(name, ParticlesEffect::name()))
node = allocMBObject<ParticlesEffect>();
else if (equalAZaz09(name, OctopusEffect::name()))
node = allocMBObject<OctopusEffect>();
else if (equalAZaz09(name, PacManEffect::name()))
node = allocMBObject<PacManEffect>();
else if (equalAZaz09(name, PopCornEffect::name()))
node = allocMBObject<PopCornEffect>();
else if (equalAZaz09(name, RainbowEffect::name()))
node = allocMBObject<RainbowEffect>();
else if (equalAZaz09(name, RainEffect::name()))
node = allocMBObject<RainEffect>();
else if (equalAZaz09(name, TetrixEffect::name()))
node = allocMBObject<TetrixEffect>();
else if (equalAZaz09(name, WaverlyEffect::name()))
node = allocMBObject<WaverlyEffect>();

// FastLED
else if (equalAZaz09(name, RainbowEffect::name()))
node = allocMBObject<RainbowEffect>();

// Moving head effects, alphabetically

else if (equalAZaz09(name, AmbientMoveEffect::name()))
Expand Down Expand Up @@ -268,8 +326,8 @@ class ModuleEffects : public NodeManager {
node->constructor(layerP.layers[0], controls); // pass the layer to the node
// node->moduleControl = _moduleLightsControl; // to access global lights control functions if needed
// node->moduleIO = _moduleIO; // to get pin allocations
node->moduleNodes = (Module*)this; // to request UI update
node->setup(); // run the setup of the effect
node->moduleNodes = (Module*)this; // to request UI update
node->setup(); // run the setup of the effect
node->onSizeChanged(Coord3D());
// layers[0]->nodes.reserve(index+1);
if (index >= layerP.layers[0]->nodes.size())
Expand Down
2 changes: 1 addition & 1 deletion src/MoonLight/Nodes/Drivers/D__Sandbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// add documentation in /docs/moonlight/drivers.md
class ExampleDriver : public Node {
public:
static const char* name() { return "Example Driver"; }
static const char* name() { return "Example"; }
static uint8_t dim() { return _NoD; } // Dimensions not relevant for drivers?
static const char* tags() { return "☸️⏳"; } // use emojis see https://moonmodules.org/MoonLight/moonlight/overview/#emoji-coding, ☸️ for drivers

Expand Down
26 changes: 26 additions & 0 deletions src/MoonLight/Nodes/Effects/E_FastLED.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,30 @@

#if FT_MOONLIGHT

class RainbowEffect : public Node {
public:
static const char* name() { return "Rainbow"; }
static uint8_t dim() { return _1D; }
static const char* tags() { return "🔥⚡️"; }

uint8_t speed = 8; // default 8*32 = 256 / 256 = 1 = hue++
uint8_t deltaHue = 7;
uint8_t chanceOfGlitter = 80;

void setup() {
addControl(speed, "speed", "slider", 0, 32);
addControl(deltaHue, "deltaHue", "slider", 0, 32);
addControl(chanceOfGlitter, "chanceOfGlitter", "slider", 0, 100);
}

uint16_t hue = 0;

void loop() override {
layer->fill_rainbow((hue += speed * 32) >> 8, deltaHue); // hue back to uint8_t
if (chanceOfGlitter && random8() < chanceOfGlitter) {
layer->setRGB(random16(layer->size.x), CRGB::White);
}
}
};

#endif
Loading