Skip to content
Open
46 changes: 46 additions & 0 deletions wled00/FX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4861,6 +4861,49 @@ static const char _data_FX_MODE_FLOWSTRIPE[] PROGMEM = "Flow Stripe@Hue speed,Ef
#define XY(x,y) SEGMENT.XY(x,y)


#ifdef WLED_USE_AA_PIXELS
/////////////////////////////
// 2D Analog Clock //
/////////////////////////////
uint16_t mode_2DAnalogClock(void) { // By Andras Fekete (bandi13)
if (!strip.isMatrix) return mode_static(); // not a 2D set-up

const uint16_t cols = SEGMENT.virtualWidth();
const uint16_t rows = SEGMENT.virtualHeight();
const uint16_t centerX = cols >> 1;
const uint16_t centerY = rows >> 1;
const uint16_t radius = min(centerX, centerY);

auto hours_in_day = (localTime / (60 * 60)) % 12;
auto minutes_in_day = (localTime / (60)) % 60;
auto seconds_in_day = (localTime) % 60;

float hour_angle = radians(360 * (hours_in_day + minutes_in_day / 60.0) / 12 - 90);
uint16_t hour_len = radius * 0.5;
uint16_t hour_x = centerX + hour_len * cos_t(hour_angle);
uint16_t hour_y = centerY + hour_len * sin_t(hour_angle);

float minute_angle = radians(360 * (minutes_in_day + seconds_in_day / 60.0) / 60 - 90);
uint16_t minute_len = radius * 0.7;
uint16_t minute_x = centerX + minute_len * cos_t(minute_angle);
uint16_t minute_y = centerY + minute_len * sin_t(minute_angle);

float second_angle = radians(360 * seconds_in_day / 60 - 90);
uint16_t second_len = radius * 0.9;
uint16_t second_x = centerX + second_len * cos_t(second_angle);
uint16_t second_y = centerY + second_len * sin_t(second_angle);

SEGMENT.fill(BLACK);
SEGMENT.drawCircleAntialiased(centerX, centerY, radius, 0x333333);
SEGMENT.drawLineAntialiased(centerX, centerY, second_x, second_y, BLUE);
SEGMENT.drawLineAntialiased(centerX, centerY, minute_x, minute_y, GREEN);
SEGMENT.drawLineAntialiased(centerX, centerY, hour_x, hour_y, RED);

return (1000 / WLED_FPS); // calculate once per second
} // mode_2DAnalogClock()
static const char _data_FX_MODE_2DANALOGCLOCK[] PROGMEM = "Analog Clock 2D@;";
#endif

// Black hole
uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline
if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up
Expand Down Expand Up @@ -8092,6 +8135,9 @@ void WS2812FX::setupEffectData() {

addEffect(FX_MODE_2DGEQ, &mode_2DGEQ, _data_FX_MODE_2DGEQ); // audio

#ifdef WLED_USE_AA_PIXELS
addEffect(FX_MODE_2DANALOGCLOCK, &mode_2DAnalogClock, _data_FX_MODE_2DANALOGCLOCK);
#endif
addEffect(FX_MODE_2DNOISE, &mode_2Dnoise, _data_FX_MODE_2DNOISE);

addEffect(FX_MODE_2DFIRENOISE, &mode_2Dfirenoise, _data_FX_MODE_2DFIRENOISE);
Expand Down
7 changes: 6 additions & 1 deletion wled00/FX.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,9 @@
#define FX_MODE_WAVESINS 184
#define FX_MODE_ROCKTAVES 185
#define FX_MODE_2DAKEMI 186
#define FX_MODE_2DANALOGCLOCK 187

#define MODE_COUNT 187
#define MODE_COUNT 188

typedef enum mapping1D2D {
M12_Pixels = 0,
Expand Down Expand Up @@ -625,9 +626,13 @@ typedef struct Segment {
void moveY(int8_t delta, bool wrap = false);
void move(uint8_t dir, uint8_t delta, bool wrap = false);
void draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
#ifdef WLED_USE_AA_PIXELS
void drawCircleAntialiased(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
#endif
void fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c);
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c);
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
void drawLineAntialiased(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c);
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, int8_t rotate = 0);
inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0)); } // automatic inline
inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, int8_t rotate = 0) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0), rotate); } // automatic inline
Expand Down
59 changes: 57 additions & 2 deletions wled00/FX_2Dfcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
for (unsigned j = 0; j < dim1; j++) {
unsigned x = vertical ? i : j;
unsigned y = vertical ? j : i;
setPixelColorXY(x, y, tmp[j]);
setPixelColorXY((int)x, (int)y, tmp[j]);
}
}

Expand Down Expand Up @@ -471,6 +471,34 @@ void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
}
}

#ifdef WLED_USE_AA_PIXELS
void Segment::drawCircleAntialiased(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
if (!isActive() || radius == 0) return; // not active
const uint16_t cols = virtualWidth();
const uint16_t rows = virtualHeight();
// Bresenham’s Algorithm
int d = 3 - (2*radius);
int y = radius, x = 0;
while (y >= x) {
setPixelColorXY(((float)cx+x-0.5)/cols, ((float)cy+y-0.5)/rows, col, true);
setPixelColorXY(((float)cx-x+0.5)/cols, ((float)cy+y-0.5)/rows, col, true);
setPixelColorXY(((float)cx+x-0.5)/cols, ((float)cy-y+0.5)/rows, col, true);
setPixelColorXY(((float)cx-x+0.5)/cols, ((float)cy-y+0.5)/rows, col, true);
setPixelColorXY(((float)cx+y-0.5)/cols, ((float)cy+x-0.5)/rows, col, true);
setPixelColorXY(((float)cx-y+0.5)/cols, ((float)cy+x-0.5)/rows, col, true);
setPixelColorXY(((float)cx+y-0.5)/cols, ((float)cy-x+0.5)/rows, col, true);
setPixelColorXY(((float)cx-y+0.5)/cols, ((float)cy-x+0.5)/rows, col, true);
x++;
if (d > 0) {
y--;
d += 4 * (x - y) + 10;
} else {
d += 4 * x + 6;
}
}
}
#endif

// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
if (!isActive() || radius == 0) return; // not active
Expand All @@ -491,7 +519,7 @@ void Segment::nscale8(uint8_t scale) {
const unsigned cols = virtualWidth();
const unsigned rows = virtualHeight();
for (unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) {
setPixelColorXY(x, y, CRGB(getPixelColorXY(x, y)).nscale8(scale));
setPixelColorXY((int)x, (int)y, CRGB(getPixelColorXY(x, y)).nscale8(scale));
}
}

Expand All @@ -513,6 +541,33 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
}
}

//line function
void Segment::drawLineAntialiased(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) {
if (!isActive()) return; // not active
const uint16_t cols = virtualWidth();
const uint16_t rows = virtualHeight();
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
const int16_t dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
const int16_t dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
int16_t err = (dx-dy)/2, e2, x2;
int16_t ed = (dx+dy == 0) ? 1 : sqrt((float)dx*dx + (float)dy*dy);

for (;;) {
Copy link
Member

@softhack007 softhack007 May 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding style: please re-write this for loop into a while{} or do{}while loop that does not rely on existing with break. The gcc optimizer will thank you ;-)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function's style is nearly identical to the existing drawLine() including the for (;;) loop.

setPixelColorXY(x0,y0,color_blend(c,getPixelColorXY(x0,y0),0xFFFF * abs(err - dx + dy) / ed, true));
e2 = err; x2 = x0;
if (e2 >= -dx) {
if(x0 == x1) break;
if (e2+dy < ed) setPixelColorXY(x0,y0+sy, color_blend(c,getPixelColorXY(x0,y0+sy), 0xFFFF * (e2+dy)/ed, true));
err -= dy; x0 += sx;
}
if (e2 <= dy) {
if (y0 == y1) break;
if (dx-e2 < ed) setPixelColorXY(x2+sx, y0, color_blend(c,getPixelColorXY(x2+sx,y0), 0xFFFF * (dx-e2)/ed, true));
err += dx; y0 += sy;
}
}
}

#include "src/font/console_font_4x6.h"
#include "src/font/console_font_5x8.h"
#include "src/font/console_font_5x12.h"
Expand Down