diff --git a/index.h b/index.h index f65f655..41c9d60 100644 --- a/index.h +++ b/index.h @@ -23,10 +23,23 @@ const char index_html[] PROGMEM = R"rawliteral( } .text-controls { margin-top: 20px; + border: 1px solid #ccc; + padding: 10px; + margin-bottom: 10px; } .text-input-group { margin-bottom: 10px; } + .param-explanation { + font-size: 0.8em; + color: #666; + } + pre { + text-align: left; + background-color: #f0f0f0; + padding: 10px; + white-space: pre-wrap; + } @@ -39,19 +52,89 @@ const char index_html[] PROGMEM = R"rawliteral( 100
+
-

Send Text

+

Add Text Node (Full Control)

+
void addNewTextNode(char text[TEXT_MAX_LENGTH + 1], uint32_t color, bool handle_pos_via_cursor = true, short pos_x = 0, short pos_y = 0, unsigned char scroll_slowness = 1, bool is_scrolling = true, bool is_small = true, short disappear_time = -1)
+
The text to display.
+
+
+
Color of the text.
+
+
+ +
X coordinate of the text.
+
+
+ +
Y coordinate of the text.
+
+
+ +
Font size of the text.
+
+
+
Animation slowness (0-255).
+
+
+ + +
If checked, the text will wrap around the screen.
+
-
+ +
+

Add Multicolor Text Node

+
void addNewMultiColor(char text[TEXT_MAX_LENGTH + 1], RGBWithIndex colors[4], unsigned char color_count, bool handle_pos_via_cursor = true, short pos_x = 0, short pos_y = 0, unsigned char scroll_slowness = 1, bool is_scrolling = true, bool is_small = true, short disappear_time = -1)
+
+ +
The text to display.
+
+
+ +
Comma-separated list of hex colors (max 4).
+
+
+ +
X coordinate of the text.
+
+
+ +
Y coordinate of the text.
+
+
+ +
Font size of the text.
+
+
+ +
Animation slowness (0-255).
+
+
+ + +
If checked, the text will wrap around the screen.
+
+
+ +
+
+ diff --git a/ledy.ino b/ledy.ino index b4ea307..ccd0425 100644 --- a/ledy.ino +++ b/ledy.ino @@ -40,8 +40,8 @@ short getTextNodeX2(TextNode *node) void addNewTextNode ( - char text[TEXT_MAX_LENGTH + 1], uint32_t color, bool handle_pos_via_cursor = true, short pos_x = 0, short pos_y = 0, - unsigned char scroll_slowness = 1, bool is_scrolling = true, bool is_small = true, short disappear_time = -1 + char text[TEXT_MAX_LENGTH + 1], uint32_t color, bool handle_pos_via_cursor, short pos_x, short pos_y, + unsigned char scroll_slowness, bool is_scrolling, bool is_small, short disappear_time, bool is_repeating ) { unsigned char text_length = strlen(text); @@ -69,6 +69,7 @@ void addNewTextNode text_nodes[i].character_count = text_length; text_nodes[i].scroll_slowness = scroll_slowness; text_nodes[i].is_scrolling = is_scrolling; + text_nodes[i].is_repeating = is_repeating; text_nodes[i].disappear_time = disappear_time; ever_created_text_nodes++; @@ -103,7 +104,14 @@ void scrollAllScrollableTexts(bool split_scroll_mode = false) { if (x2 < 0) { - text_nodes[i].disappear_time = 1; + if (text_nodes[i].is_repeating) + { + text_nodes[i].pos_x = DISPLAY_MAX_X; + } + else + { + text_nodes[i].disappear_time = 1; + } continue; } text_nodes[i].pos_x--; @@ -112,7 +120,14 @@ void scrollAllScrollableTexts(bool split_scroll_mode = false) { if (x1 > DISPLAY_MAX_X) { - text_nodes[i].disappear_time = 1; + if (text_nodes[i].is_repeating) + { + text_nodes[i].pos_x = -getTextNodeX2(&text_nodes[i]) + text_nodes[i].pos_x; + } + else + { + text_nodes[i].disappear_time = 1; + } continue; } text_nodes[i].pos_x++; @@ -137,8 +152,8 @@ void scrollAllScrollableTexts(bool split_scroll_mode = false) void addNewMultiColor ( - char text[TEXT_MAX_LENGTH + 1], RGBWithIndex colors[4], unsigned char color_count, bool handle_pos_via_cursor = true, short pos_x = 0, short pos_y = 0, - unsigned char scroll_slowness = 1, bool is_scrolling = true, bool is_small = true, short disappear_time = -1 + char text[TEXT_MAX_LENGTH + 1], RGBWithIndex colors[4], unsigned char color_count, bool handle_pos_via_cursor, short pos_x, short pos_y, + unsigned char scroll_slowness, bool is_scrolling, bool is_small, short disappear_time, bool is_repeating ) { unsigned char text_length = strlen(text); @@ -170,6 +185,7 @@ void addNewMultiColor multi_color_text_node[i].character_count = text_length; multi_color_text_node[i].scroll_slowness = scroll_slowness; multi_color_text_node[i].is_scrolling = is_scrolling; + multi_color_text_node[i].is_repeating = is_repeating; multi_color_text_node[i].disappear_time = disappear_time; ever_created_multi_color_text_nodes++; @@ -210,7 +226,14 @@ void scrollAllMultiColorTexts(bool split_scroll_mode = false) { if (x2 < 0) { - multi_color_text_node[i].disappear_time = 1; + if (multi_color_text_node[i].is_repeating) + { + multi_color_text_node[i].pos_x = DISPLAY_MAX_X; + } + else + { + multi_color_text_node[i].disappear_time = 1; + } continue; } multi_color_text_node[i].pos_x--; @@ -219,7 +242,14 @@ void scrollAllMultiColorTexts(bool split_scroll_mode = false) { if (x1 > DISPLAY_MAX_X) { - multi_color_text_node[i].disappear_time = 1; + if (multi_color_text_node[i].is_repeating) + { + multi_color_text_node[i].pos_x = -getMultiColorTextNodeX2(&multi_color_text_node[i]) + multi_color_text_node[i].pos_x; + } + else + { + multi_color_text_node[i].disappear_time = 1; + } continue; } multi_color_text_node[i].pos_x++; diff --git a/prototypes.h b/prototypes.h index d8008bf..f7f674f 100644 --- a/prototypes.h +++ b/prototypes.h @@ -16,9 +16,9 @@ void drawImageFromMemoryByIndex(unsigned char image_index, short pos_x, short po void setPixel(short x, short y, uint32_t color); void start_server(); void handle_server(); -void addNewTextNode(char text[TEXT_MAX_LENGTH + 1], uint32_t color, bool handle_pos_via_cursor, short pos_x, short pos_y, unsigned char scroll_slowness, bool is_scrolling, bool is_small, short disappear_time); +void addNewTextNode(char text[TEXT_MAX_LENGTH + 1], uint32_t color, bool handle_pos_via_cursor, short pos_x, short pos_y, unsigned char scroll_slowness, bool is_scrolling, bool is_small, short disappear_time, bool is_repeating = false); void scrollAllScrollableTexts(bool split_scroll_mode); -void addNewMultiColor(char text[TEXT_MAX_LENGTH + 1], RGBWithIndex colors[4], unsigned char color_count, bool handle_pos_via_cursor, short pos_x, short pos_y, unsigned char scroll_slowness, bool is_scrolling, bool is_small, short disappear_time); +void addNewMultiColor(char text[TEXT_MAX_LENGTH + 1], RGBWithIndex colors[4], unsigned char color_count, bool handle_pos_via_cursor, short pos_x, short pos_y, unsigned char scroll_slowness, bool is_scrolling, bool is_small, short disappear_time, bool is_repeating = false); void scrollAllMultiColorTexts(bool split_scroll_mode); void drawCharacter(const bool (*character)[5], unsigned char height, unsigned char width, uint32_t color, Cursor (*used_cursor)); void handleDisappearTimers(); diff --git a/server.ino b/server.ino index 85375d2..1d7837a 100644 --- a/server.ino +++ b/server.ino @@ -98,27 +98,124 @@ void handleBmpUpload() { void handleText() { - if (server.hasArg("text") && server.hasArg("color") && server.hasArg("position") && server.hasArg("slowness")) { + if (server.hasArg("text") && server.hasArg("color") && server.hasArg("slowness")) { String text_str = server.arg("text"); String colorStr = server.arg("color"); - String position = server.arg("position"); unsigned char slowness = server.arg("slowness").toInt(); short disappear_time = server.hasArg("disappear") ? server.arg("disappear").toInt() : -1; + bool is_small = true; + if (server.hasArg("fontSize") && server.arg("fontSize") != "") { + if (server.arg("fontSize") == "medium") { + is_small = false; + } + } + + bool is_repeating = false; + if (server.hasArg("is_repeating")) { + is_repeating = server.arg("is_repeating") == "true"; + } char text[TEXT_MAX_LENGTH + 1]; text_str.toCharArray(text, TEXT_MAX_LENGTH + 1); uint32_t color = strtol(colorStr.substring(1).c_str(), NULL, 16); - if (position == "top") { - addNewTextNode(text, color, false, 43, 0, slowness, true, false, disappear_time); - } else if (position == "bottom") { - addNewTextNode(text, color, false, -text_str.length() * 6, 9, slowness, true, false, disappear_time); + if (server.hasArg("position")) { + String position = server.arg("position"); + if (position == "top") { + addNewTextNode(text, color, false, 43, 0, slowness, true, is_small, disappear_time, is_repeating); + } else if (position == "bottom") { + addNewTextNode(text, color, false, -text_str.length() * 6, 9, slowness, true, is_small, disappear_time, is_repeating); + } + server.send(200, "text/plain", "OK"); + } else { + short x = 0; + short y = 0; + if (server.hasArg("x") && server.arg("x") != "") { + x = server.arg("x").toInt(); + } + if (server.hasArg("y") && server.arg("y") != "") { + y = server.arg("y").toInt(); + } + addNewTextNode(text, color, false, x, y, slowness, true, is_small, disappear_time, is_repeating); + server.send(200, "text/plain", "OK"); } + } else { + server.send(400, "text/plain", "Invalid arguments for /text"); + } +} + +void handleMulticolorText() { + if (server.hasArg("text") && server.hasArg("colors") && server.hasArg("slowness")) { + String text_str = server.arg("text"); + String colors_str = server.arg("colors"); + unsigned char slowness = server.arg("slowness").toInt(); + short disappear_time = server.hasArg("disappear") ? server.arg("disappear").toInt() : -1; + bool is_small = true; + if (server.hasArg("fontSize") && server.arg("fontSize") != "") { + if (server.arg("fontSize") == "medium") { + is_small = false; + } + } + bool is_repeating = false; + if (server.hasArg("is_repeating")) { + is_repeating = server.arg("is_repeating") == "true"; + } + + char text[TEXT_MAX_LENGTH + 1]; + text_str.toCharArray(text, TEXT_MAX_LENGTH + 1); + + RGBWithIndex colors[4]; + int color_count = 0; + String color_part = ""; + int last_comma = -1; + for (int i = 0; i < colors_str.length() && color_count < 4; i++) { + if (colors_str.charAt(i) == ',') { + color_part = colors_str.substring(last_comma + 1, i); + last_comma = i; + if (color_part.length() > 0) { + long color_val = strtol(color_part.substring(1).c_str(), NULL, 16); + colors[color_count].r = (color_val >> 16) & 0xFF; + colors[color_count].g = (color_val >> 8) & 0xFF; + colors[color_count].b = color_val & 0xFF; + color_count++; + } + } + } + // last color + if (color_count < 4) { + color_part = colors_str.substring(last_comma + 1); + if (color_part.length() > 0) { + long color_val = strtol(color_part.substring(1).c_str(), NULL, 16); + colors[color_count].r = (color_val >> 16) & 0xFF; + colors[color_count].g = (color_val >> 8) & 0xFF; + colors[color_count].b = color_val & 0xFF; + color_count++; + } + } + + if (color_count > 0) { + int text_len = text_str.length(); + int part_len = text_len / color_count; + for (int i = 0; i < color_count; i++) { + colors[i].start_index = i * part_len; + } + } + + short x = 0; + short y = 0; + if (server.hasArg("x") && server.arg("x") != "") { + x = server.arg("x").toInt(); + } + if (server.hasArg("y") && server.arg("y") != "") { + y = server.arg("y").toInt(); + } + + addNewMultiColor(text, colors, color_count, false, x, y, slowness, true, is_small, disappear_time, is_repeating); server.send(200, "text/plain", "OK"); } else { - server.send(400, "text/plain", "Invalid arguments"); + server.send(400, "text/plain", "Invalid arguments for /multicolor-text"); } } @@ -137,6 +234,7 @@ void start_server() server.on("/", handleRoot); server.on("/text", HTTP_POST, handleText); + server.on("/multicolor-text", HTTP_POST, handleMulticolorText); server.on("/brightness", HTTP_POST, handleBrightness); server.on("/upload-page", HTTP_GET, handleUploadPage); server.on("/upload-bmp", HTTP_POST, []() { diff --git a/structs.h b/structs.h index 8194917..fd2ab16 100644 --- a/structs.h +++ b/structs.h @@ -34,9 +34,10 @@ struct TextNode unsigned char scroll_progress; short disappear_time; bool is_scrolling; + bool is_repeating; - TextNode() : color(0), pos_x(0), pos_y(0), character_count(0), scroll_slowness(0), scroll_progress(0), characterSize({7,5}), disappear_time(0), is_scrolling(true) {} + TextNode() : color(0), pos_x(0), pos_y(0), character_count(0), scroll_slowness(0), scroll_progress(0), characterSize({7,5}), disappear_time(0), is_scrolling(true), is_repeating(false) {} }; struct RGB @@ -77,8 +78,9 @@ struct MultiColorTextNode unsigned char scroll_progress; short disappear_time; bool is_scrolling; + bool is_repeating; - MultiColorTextNode() : pos_x(0), pos_y(0), character_count(0), scroll_slowness(0), scroll_progress(0), characterSize({7,5}), disappear_time(0), is_scrolling(true), color_count(0) {} + MultiColorTextNode() : pos_x(0), pos_y(0), character_count(0), scroll_slowness(0), scroll_progress(0), characterSize({7,5}), disappear_time(0), is_scrolling(true), color_count(0), is_repeating(false) {} }; struct Image