|
11 | 11 | #include <pbsys/main.h> |
12 | 12 | #include <pbsys/status.h> |
13 | 13 |
|
| 14 | +#include <pbdrv/clock.h> |
14 | 15 | #include <pbdrv/display.h> |
15 | 16 |
|
16 | | -#include <pbio/light_animation.h> |
17 | 17 | #include <pbio/battery.h> |
| 18 | +#include <pbio/busy_count.h> |
18 | 19 | #include <pbio/button.h> |
19 | 20 | #include <pbio/image.h> |
20 | | -#include <pbio/version.h> |
21 | 21 | #include <pbio/int_math.h> |
| 22 | +#include <pbio/light_animation.h> |
| 23 | +#include <pbio/version.h> |
22 | 24 |
|
23 | 25 | #include "hmi_ev3_ui.h" |
24 | 26 | #include "pbio_image_media.h" |
@@ -315,7 +317,7 @@ static void pbsys_hmi_ev3_ui_draw_centered_text(const pbio_font_t *font, const c |
315 | 317 | pbio_image_rect_t rect; |
316 | 318 | pbio_image_bbox_text(font, text, strlen(text), &rect); |
317 | 319 | int x = (display->width - rect.width) / 2 + x_offset; |
318 | | - pbio_image_draw_text(display, &pbio_font_terminus_normal_16, x, y, text, strlen(text), BLACK); |
| 320 | + pbio_image_draw_text(display, font, x, y, text, strlen(text), BLACK); |
319 | 321 | } |
320 | 322 |
|
321 | 323 | /** |
@@ -488,26 +490,22 @@ static void pbsys_hmi_ev3_ui_draw_pybricks_logo(uint32_t x, uint32_t y, uint32_t |
488 | 490 |
|
489 | 491 | pbio_image_t *display = pbdrv_display_get_image(); |
490 | 492 |
|
491 | | - uint8_t v = pbdrv_display_get_max_value(); |
492 | | - |
493 | 493 | // Rounded rectangles making up the left and right side of the head. |
494 | | - pbio_image_fill_rounded_rect(display, sx(0), sy(0), sr(42), sr(84), sr(11), v); |
495 | | - pbio_image_fill_rounded_rect(display, sx(112), sy(0), sr(42), sr(84), sr(11), v); |
| 494 | + pbio_image_fill_rounded_rect(display, sx(0), sy(0), sr(42), sr(84), sr(11), BLACK); |
| 495 | + pbio_image_fill_rounded_rect(display, sx(112), sy(0), sr(42), sr(84), sr(11), BLACK); |
496 | 496 |
|
497 | 497 | // Forehead, main fill, and jaw. |
498 | | - pbio_image_fill_rect(display, sx(14), sy(0), sr(126), sr(14), v); |
| 498 | + pbio_image_fill_rect(display, sx(14), sy(0), sr(126), sr(14), BLACK); |
499 | 499 | pbio_image_fill_rect(display, sx(14), sy(14), sr(126), sr(56), 0); |
500 | | - pbio_image_fill_rect(display, sx(28), sy(56), sr(98), sr(14), v); |
| 500 | + pbio_image_fill_rect(display, sx(28), sy(56), sr(98), sr(14), BLACK); |
501 | 501 |
|
502 | 502 | // Eyes. |
503 | | - if (!blink) { |
504 | | - pbio_image_fill_circle(display, sx(49), sy(29), sr(10), v); |
505 | | - pbio_image_fill_circle(display, sx(106), sy(29), sr(10), v); |
506 | | - } |
| 503 | + pbio_image_fill_circle(display, sx(49), sy(29), sr(10), blink ? WHITE : BLACK); |
| 504 | + pbio_image_fill_circle(display, sx(106), sy(29), sr(10), blink ? WHITE : BLACK); |
507 | 505 |
|
508 | 506 | // Teeth. |
509 | 507 | for (uint32_t i = 0; i < 6; i++) { |
510 | | - pbio_image_fill_rect(display, sx(40 + 14 * i), sy(51), sr(4), sr(5), v); |
| 508 | + pbio_image_fill_rect(display, sx(40 + 14 * i), sy(51), sr(4), sr(5), BLACK); |
511 | 509 | } |
512 | 510 | } |
513 | 511 |
|
@@ -553,6 +551,106 @@ static uint32_t pbsys_hmi_ev3_ui_run_animation_next(pbio_light_animation_t *anim |
553 | 551 | return ANIMATION_REFRESH_MS; |
554 | 552 | } |
555 | 553 |
|
| 554 | +// List of supporters created during build process. |
| 555 | +extern const char *const hmi_ev3_ui_credits_names[]; |
| 556 | +extern const size_t hmi_ev3_ui_credits_size; |
| 557 | + |
| 558 | +#define NUM_NAMES_PER_PAGE (7) |
| 559 | + |
| 560 | +static const char *pbsys_hmi_ev3_ui_closing_credits_get_name(size_t page, size_t entry) { |
| 561 | + |
| 562 | + // Choose first name randomly, keeping order. |
| 563 | + static size_t random = SIZE_MAX; |
| 564 | + if (random == SIZE_MAX) { |
| 565 | + random = pbdrv_clock_get_ms() % hmi_ev3_ui_credits_size; |
| 566 | + } |
| 567 | + |
| 568 | + size_t offset = page * NUM_NAMES_PER_PAGE + entry; |
| 569 | + if (offset >= hmi_ev3_ui_credits_size) { |
| 570 | + // Last page may contain some empty entries. |
| 571 | + return NULL; |
| 572 | + } |
| 573 | + |
| 574 | + return hmi_ev3_ui_credits_names[(random + offset) % hmi_ev3_ui_credits_size]; |
| 575 | +} |
| 576 | + |
| 577 | +pbio_error_t pbsys_hmi_ev3_ui_closing_credits(pbio_os_state_t *state, void *context) { |
| 578 | + |
| 579 | + pbio_image_t *display = pbdrv_display_get_image(); |
| 580 | + |
| 581 | + static pbio_os_timer_t timer; |
| 582 | + static size_t page; |
| 583 | + |
| 584 | + // Pressing cancel exits closing credits. |
| 585 | + if (pbdrv_button_get_pressed() & PBIO_BUTTON_LEFT_UP) { |
| 586 | + goto close; |
| 587 | + } |
| 588 | + |
| 589 | + PBIO_OS_ASYNC_BEGIN(state); |
| 590 | + |
| 591 | + // Display all supporter names across several pages. |
| 592 | + for (page = 0; page < (hmi_ev3_ui_credits_size + NUM_NAMES_PER_PAGE - 1) / NUM_NAMES_PER_PAGE; page++) { |
| 593 | + |
| 594 | + pbio_image_fill(display, WHITE); |
| 595 | + |
| 596 | + // Populate page with list of names to fit. |
| 597 | + for (size_t entry = 0; entry < NUM_NAMES_PER_PAGE; entry++) { |
| 598 | + const char *name = pbsys_hmi_ev3_ui_closing_credits_get_name(page, entry); |
| 599 | + if (!name) { |
| 600 | + continue; |
| 601 | + } |
| 602 | + int name_y = 28 + entry * display->print_font->line_height; |
| 603 | + pbio_image_draw_text(display, &pbio_font_terminus_normal_16, 10, name_y, name, strlen(name), BLACK); |
| 604 | + } |
| 605 | + |
| 606 | + // Header with line. |
| 607 | + const char *thanks = "Thanks to our supporters!"; |
| 608 | + pbio_image_draw_text(display, &pbio_font_mono_8x5_8, 10, 12, thanks, strlen(thanks), BLACK); |
| 609 | + pbio_image_draw_hline(display, 0, 14, 178, 3); |
| 610 | + |
| 611 | + // Show the page. |
| 612 | + pbdrv_display_update(); |
| 613 | + PBIO_OS_AWAIT_MS(state, &timer, 1000); |
| 614 | + } |
| 615 | + |
| 616 | + // Display creator info. |
| 617 | + pbio_image_fill(display, WHITE); |
| 618 | + const char *thanks = "Made by:"; |
| 619 | + pbio_image_draw_hline(display, 0, 14, 178, 3); |
| 620 | + pbio_image_draw_text(display, &pbio_font_mono_8x5_8, 10, 12, thanks, strlen(thanks), BLACK); |
| 621 | + pbsys_hmi_ev3_ui_draw_centered_text(&pbio_font_terminus_normal_16, "Laurens Valk", 0, 40); |
| 622 | + pbsys_hmi_ev3_ui_draw_centered_text(&pbio_font_terminus_normal_16, "David Lechner", 0, 70); |
| 623 | + pbsys_hmi_ev3_ui_draw_centered_text(&pbio_font_terminus_normal_16, "Pybricks Community", 0, 100); |
| 624 | + pbdrv_display_update(); |
| 625 | + PBIO_OS_AWAIT_MS(state, &timer, 1500); |
| 626 | + |
| 627 | + // Display animated Pybricks thanks message. |
| 628 | + pbio_image_fill(display, WHITE); |
| 629 | + pbio_image_draw_image_transparent_from_monochrome(display, &pbio_image_media_pybricks_join, 31, 6, BLACK); |
| 630 | + pbdrv_display_update(); |
| 631 | + PBIO_OS_AWAIT_MS(state, &timer, 1500); |
| 632 | + pbio_image_fill(display, WHITE); |
| 633 | + pbsys_hmi_ev3_ui_draw_pybricks_logo(12, 12, 154, false); |
| 634 | + pbsys_hmi_ev3_ui_draw_centered_text(&pbio_font_terminus_normal_16, "Thanks for your help!", 0, 114); |
| 635 | + pbdrv_display_update(); |
| 636 | + PBIO_OS_AWAIT_MS(state, &timer, 500); |
| 637 | + pbsys_hmi_ev3_ui_draw_pybricks_logo(12, 12, 154, true); |
| 638 | + pbdrv_display_update(); |
| 639 | + PBIO_OS_AWAIT_MS(state, &timer, 400); |
| 640 | + pbsys_hmi_ev3_ui_draw_pybricks_logo(12, 12, 154, false); |
| 641 | + pbdrv_display_update(); |
| 642 | + PBIO_OS_AWAIT_MS(state, &timer, 600); |
| 643 | + |
| 644 | +close: |
| 645 | + |
| 646 | + // Prepare for shutdown and release lock. |
| 647 | + pbio_image_fill(display, WHITE); |
| 648 | + pbdrv_display_update(); |
| 649 | + pbio_busy_count_down(); |
| 650 | + |
| 651 | + PBIO_OS_ASYNC_END(PBIO_SUCCESS); |
| 652 | +} |
| 653 | + |
556 | 654 | /** |
557 | 655 | * User animation state. |
558 | 656 | */ |
|
0 commit comments