Scrolling text enhancement.
- breaking change - remove leading 0 checkmark - add reverse scroll checkmark - add vertical scroll if text fits into segment (intensity ==0 or ==255) - rotated characters - leading 0 check added to short texts (i.e. #DDMM0) Fixes #3322
This commit is contained in:
parent
ac83b67632
commit
4911a74cac
@ -5786,8 +5786,8 @@ uint16_t mode_2Dscrollingtext(void) {
|
||||
const uint16_t cols = SEGMENT.virtualWidth();
|
||||
const uint16_t rows = SEGMENT.virtualHeight();
|
||||
|
||||
int letterWidth;
|
||||
int letterHeight;
|
||||
int letterWidth, rotLW;
|
||||
int letterHeight, rotLH;
|
||||
switch (map(SEGMENT.custom2, 0, 255, 1, 5)) {
|
||||
default:
|
||||
case 1: letterWidth = 4; letterHeight = 6; break;
|
||||
@ -5796,59 +5796,83 @@ uint16_t mode_2Dscrollingtext(void) {
|
||||
case 4: letterWidth = 7; letterHeight = 9; break;
|
||||
case 5: letterWidth = 5; letterHeight = 12; break;
|
||||
}
|
||||
const bool zero = SEGMENT.check3;
|
||||
const int yoffset = map(SEGMENT.intensity, 0, 255, -rows/2, rows/2) + (rows-letterHeight)/2;
|
||||
// letters are rotated
|
||||
if (((SEGMENT.custom3+1)>>3) % 2) {
|
||||
rotLH = letterWidth;
|
||||
rotLW = letterHeight;
|
||||
} else {
|
||||
rotLW = letterWidth;
|
||||
rotLH = letterHeight;
|
||||
}
|
||||
|
||||
char text[WLED_MAX_SEGNAME_LEN+1] = {'\0'};
|
||||
if (SEGMENT.name) for (size_t i=0,j=0; i<strlen(SEGMENT.name); i++) if (SEGMENT.name[i]>31 && SEGMENT.name[i]<128) text[j++] = SEGMENT.name[i];
|
||||
const bool zero = strchr(text, '0') != nullptr;
|
||||
const int numberOfLetters = strlen(text);
|
||||
|
||||
if (!strlen(text)
|
||||
|| !strncmp_P(text,PSTR("#DATE"),5)
|
||||
|| !strncmp_P(text,PSTR("#DDMM"),5)
|
||||
|| !strncmp_P(text,PSTR("#MMDD"),5)
|
||||
|| !strncmp_P(text,PSTR("#TIME"),5)
|
||||
|| !strncmp_P(text,PSTR("#HHMM"),5)) { // fallback if empty segment name: display date and time
|
||||
char sec[5];
|
||||
byte AmPmHour = hour(localTime);
|
||||
boolean isitAM = true;
|
||||
if (useAMPM) {
|
||||
if (AmPmHour > 11) { AmPmHour -= 12; isitAM = false; }
|
||||
if (AmPmHour == 0) { AmPmHour = 12; }
|
||||
}
|
||||
if (useAMPM) sprintf_P(sec, PSTR(" %2s"), (isitAM ? "AM" : "PM"));
|
||||
else sprintf_P(sec, PSTR(":%02d"), second(localTime));
|
||||
if (!strncmp_P(text,PSTR("#DATE"),5)) sprintf_P(text, zero?PSTR("%02d.%02d.%04d"):PSTR("%d.%d.%d"), day(localTime), month(localTime), year(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#DDMM"),5)) sprintf_P(text, zero?PSTR("%02d.%02d"):PSTR("%d.%d"), day(localTime), month(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#MMDD"),5)) sprintf_P(text, zero?PSTR("%02d/%02d"):PSTR("%d/%d"), month(localTime), day(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#TIME"),5)) sprintf_P(text, zero?PSTR("%02d:%02d%s"):PSTR("%2d:%02d%s"), AmPmHour, minute(localTime), sec);
|
||||
else if (!strncmp_P(text,PSTR("#HHMM"),5)) sprintf_P(text, zero?PSTR("%02d:%02d"):PSTR("%d:%02d"), AmPmHour, minute(localTime));
|
||||
else sprintf_P(text, zero?PSTR("%s %02d, %04d %02d:%02d%s"):PSTR("%s %d, %d %d:%02d%s"), monthShortStr(month(localTime)), day(localTime), year(localTime), AmPmHour, minute(localTime), sec);
|
||||
char sec[5];
|
||||
int AmPmHour = hour(localTime);
|
||||
bool isitAM = true;
|
||||
if (useAMPM) {
|
||||
if (AmPmHour > 11) { AmPmHour -= 12; isitAM = false; }
|
||||
if (AmPmHour == 0) { AmPmHour = 12; }
|
||||
sprintf_P(sec, PSTR(" %2s"), (isitAM ? "AM" : "PM"));
|
||||
} else {
|
||||
sprintf_P(sec, PSTR(":%02d"), second(localTime));
|
||||
}
|
||||
|
||||
if (!numberOfLetters) { // fallback if empty segment name: display date and time
|
||||
sprintf_P(text, PSTR("%s %d, %d %d:%02d%s"), monthShortStr(month(localTime)), day(localTime), year(localTime), AmPmHour, minute(localTime), sec);
|
||||
} else {
|
||||
if (!strncmp_P(text,PSTR("#DATE"),5)) sprintf_P(text, zero?PSTR("%02d.%02d.%04d"):PSTR("%d.%d.%d"), day(localTime), month(localTime), year(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#DDMM"),5)) sprintf_P(text, zero?PSTR("%02d.%02d") :PSTR("%d.%d"), day(localTime), month(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#MMDD"),5)) sprintf_P(text, zero?PSTR("%02d/%02d") :PSTR("%d/%d"), month(localTime), day(localTime));
|
||||
else if (!strncmp_P(text,PSTR("#TIME"),5)) sprintf_P(text, zero?PSTR("%02d:%02d%s") :PSTR("%2d:%02d%s"), AmPmHour, minute(localTime), sec);
|
||||
else if (!strncmp_P(text,PSTR("#HHMM"),5)) sprintf_P(text, zero?PSTR("%02d:%02d") :PSTR("%d:%02d"), AmPmHour, minute(localTime));
|
||||
}
|
||||
|
||||
int width = (numberOfLetters * rotLW);
|
||||
int yoffset = map(SEGMENT.intensity, 0, 255, -rows/2, rows/2) + (rows-rotLH)/2;
|
||||
if (width <= cols) {
|
||||
// scroll vertically (e.g. ^^ Way out ^^) if it fits
|
||||
int speed = map(SEGMENT.speed, 0, 255, 5000, 1000);
|
||||
int frac = millis()%speed + 1;
|
||||
if (SEGMENT.intensity == 255) {
|
||||
yoffset = (2 * frac * rows)/speed - rows;
|
||||
} else if (SEGMENT.intensity == 0) {
|
||||
yoffset = rows - (2 * frac * rows)/speed;
|
||||
}
|
||||
}
|
||||
const int numberOfLetters = strlen(text);
|
||||
|
||||
if (SEGENV.step < millis()) {
|
||||
if ((numberOfLetters * letterWidth) > cols) ++SEGENV.aux0 %= (numberOfLetters * letterWidth) + cols; // offset
|
||||
else SEGENV.aux0 = (cols + (numberOfLetters * letterWidth))/2;
|
||||
// calculate start offset
|
||||
if (width > cols) {
|
||||
if (SEGMENT.check3) {
|
||||
if (SEGENV.aux0 == 0) SEGENV.aux0 = width + cols - 1;
|
||||
else --SEGENV.aux0;
|
||||
} else ++SEGENV.aux0 %= width + cols;
|
||||
} else SEGENV.aux0 = (cols + width)/2;
|
||||
++SEGENV.aux1 &= 0xFF; // color shift
|
||||
SEGENV.step = millis() + map(SEGMENT.speed, 0, 255, 10*FRAMETIME_FIXED, 2*FRAMETIME_FIXED);
|
||||
if (!SEGMENT.check2) {
|
||||
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++ )
|
||||
SEGMENT.blendPixelColorXY(x, y, SEGCOLOR(1), 255 - (SEGMENT.custom1>>1));
|
||||
}
|
||||
SEGENV.step = millis() + map(SEGMENT.speed, 0, 255, 10*FRAMETIME_FIXED, 2*FRAMETIME_FIXED); // shift letters every 238ms or 46ms
|
||||
}
|
||||
|
||||
if (!SEGMENT.check2) SEGMENT.fade_out(255 - (SEGMENT.custom1>>4)); // trail
|
||||
|
||||
for (int i = 0; i < numberOfLetters; i++) {
|
||||
if (int(cols) - int(SEGENV.aux0) + letterWidth*(i+1) < 0) continue; // don't draw characters off-screen
|
||||
int xoffset = int(cols) - int(SEGENV.aux0) + rotLW*i;
|
||||
if (xoffset + rotLW < 0) continue; // don't draw characters off-screen
|
||||
uint32_t col1 = SEGMENT.color_from_palette(SEGENV.aux1, false, PALETTE_SOLID_WRAP, 0);
|
||||
uint32_t col2 = BLACK;
|
||||
if (SEGMENT.check1 && SEGMENT.palette == 0) {
|
||||
col1 = SEGCOLOR(0);
|
||||
col2 = SEGCOLOR(2);
|
||||
}
|
||||
SEGMENT.drawCharacter(text[i], int(cols) - int(SEGENV.aux0) + letterWidth*i, yoffset, letterWidth, letterHeight, col1, col2);
|
||||
SEGMENT.drawCharacter(text[i], xoffset, yoffset, letterWidth, letterHeight, col1, col2, (SEGMENT.custom3+1)>>3);
|
||||
}
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_2DSCROLLTEXT[] PROGMEM = "Scrolling Text@!,Y Offset,Trail,Font size,,Gradient,Overlay,0;!,!,Gradient;!;2;ix=128,c1=0,rev=0,mi=0,rY=0,mY=0";
|
||||
static const char _data_FX_MODE_2DSCROLLTEXT[] PROGMEM = "Scrolling Text@!,Y Offset,Trail,Font size,Rotate letters,Gradient,Overlay,Reverse dir.;!,!,Gradient;!;2;ix=128,c1=0,c3=0,rev=0,mi=0,rY=0,mY=0";
|
||||
|
||||
|
||||
////////////////////////////
|
||||
|
@ -615,9 +615,9 @@ typedef struct Segment {
|
||||
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);
|
||||
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 drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0);
|
||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, uint8_t rotate = 0);
|
||||
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
|
||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0)); } // automatic inline
|
||||
void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2, uint8_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
|
||||
void wu_pixel(uint32_t x, uint32_t y, CRGB c);
|
||||
void blur1d(fract8 blur_amount); // blur all rows in 1 dimension
|
||||
void blur2d(fract8 blur_amount) { blur(blur_amount); }
|
||||
|
@ -569,7 +569,7 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
|
||||
|
||||
// draws a raster font character on canvas
|
||||
// only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM
|
||||
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2) {
|
||||
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, uint8_t rotate) {
|
||||
if (!isActive()) return; // not active
|
||||
if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported
|
||||
chr -= 32; // align with font table entries
|
||||
@ -582,9 +582,6 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
||||
|
||||
//if (w<5 || w>6 || h!=8) return;
|
||||
for (int i = 0; i<h; i++) { // character height
|
||||
int16_t y0 = y + i;
|
||||
if (y0 < 0) continue; // drawing off-screen
|
||||
if (y0 >= rows) break; // drawing off-screen
|
||||
uint8_t bits = 0;
|
||||
switch (font) {
|
||||
case 24: bits = pgm_read_byte_near(&console_font_4x6[(chr * h) + i]); break; // 5x8 font
|
||||
@ -596,8 +593,15 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
||||
}
|
||||
col = ColorFromPalette(grad, (i+1)*255/h, 255, NOBLEND);
|
||||
for (int j = 0; j<w; j++) { // character width
|
||||
int16_t x0 = x + (w-1) - j;
|
||||
if ((x0 >= 0 || x0 < cols) && ((bits>>(j+(8-w))) & 0x01)) { // bit set & drawing on-screen
|
||||
int x0, y0;
|
||||
switch (rotate) {
|
||||
case 3: x0 = x + (h-1) - i; y0 = y + (w-1) - j; break;
|
||||
case 2: x0 = x + j; y0 = y + (h-1) - i; break;
|
||||
case 1: x0 = x + i; y0 = y + j; break;
|
||||
default: x0 = x + (w-1) - j; y0 = y + i; break;
|
||||
}
|
||||
if (x0 < 0 || x0 >= cols || y0 < 0 || y0 >= rows) continue; // drawing off-screen
|
||||
if (((bits>>(j+(8-w))) & 0x01)) { // bit set
|
||||
setPixelColorXY(x0, y0, col);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user