From 3efbd454432e54650f596601d27eae1e86b5be98 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <thinkyhead@users.noreply.github.com>
Date: Sat, 2 Jan 2021 15:51:51 -0600
Subject: [PATCH] Improved bootscreen animation

---
 Marlin/src/lcd/dogm/dogm_Bootscreen.h | 15 +++++++++++
 Marlin/src/lcd/dogm/marlinui_DOGM.cpp | 37 +++++++++++++++------------
 2 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/Marlin/src/lcd/dogm/dogm_Bootscreen.h b/Marlin/src/lcd/dogm/dogm_Bootscreen.h
index c9001119d9d..0b8845ed794 100644
--- a/Marlin/src/lcd/dogm/dogm_Bootscreen.h
+++ b/Marlin/src/lcd/dogm/dogm_Bootscreen.h
@@ -32,8 +32,16 @@
 
 #if ENABLED(SHOW_CUSTOM_BOOTSCREEN)
 
+  typedef struct {
+    const unsigned char *bitmap;
+    const unsigned short duration;
+  } boot_frame_t;
+
   #include "../../../_Bootscreen.h"
 
+  #ifndef CUSTOM_BOOTSCREEN_BMPWIDTH
+    #define CUSTOM_BOOTSCREEN_BMPWIDTH 128
+  #endif
   #ifndef CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH
     #define CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH CEILING(CUSTOM_BOOTSCREEN_BMPWIDTH, 8)
   #endif
@@ -41,6 +49,13 @@
     #define CUSTOM_BOOTSCREEN_BMPHEIGHT (sizeof(custom_start_bmp) / (CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH))
   #endif
 
+  #ifndef CUSTOM_BOOTSCREEN_Y
+    #if ENABLED(CUSTOM_BOOTSCREEN_BOTTOM_JUSTIFY)
+      #define CUSTOM_BOOTSCREEN_Y (LCD_PIXEL_HEIGHT - (CUSTOM_BOOTSCREEN_BMPHEIGHT))
+    #else
+      #define CUSTOM_BOOTSCREEN_Y ((LCD_PIXEL_HEIGHT - (CUSTOM_BOOTSCREEN_BMPHEIGHT)) / 2)
+    #endif
+  #endif
 #endif
 
 #if ENABLED(BOOT_MARLIN_LOGO_SMALL)
diff --git a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp
index 54735175b44..87899a96beb 100644
--- a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp
+++ b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp
@@ -110,19 +110,21 @@ bool MarlinUI::detected() { return true; }
     // Draws a slice of a particular frame of the custom bootscreen, without the u8g loop
     void MarlinUI::draw_custom_bootscreen(const uint8_t frame/*=0*/) {
       constexpr u8g_uint_t left = u8g_uint_t((LCD_PIXEL_WIDTH  - (CUSTOM_BOOTSCREEN_BMPWIDTH)) / 2),
-                            top = u8g_uint_t((LCD_PIXEL_HEIGHT - (CUSTOM_BOOTSCREEN_BMPHEIGHT)) / 2);
+                            top = u8g_uint_t(CUSTOM_BOOTSCREEN_Y);
       #if ENABLED(CUSTOM_BOOTSCREEN_INVERTED)
         constexpr u8g_uint_t right = left + CUSTOM_BOOTSCREEN_BMPWIDTH,
                             bottom = top + CUSTOM_BOOTSCREEN_BMPHEIGHT;
       #endif
 
-      const u8g_pgm_uint8_t * const bmp =
-        #if ENABLED(CUSTOM_BOOTSCREEN_ANIMATED)
-          (u8g_pgm_uint8_t*)pgm_read_ptr(&custom_bootscreen_animation[frame])
-        #else
-          custom_start_bmp
-        #endif
-      ;
+      const void * const frame_ptr = pgm_read_ptr(&custom_bootscreen_animation[frame]);
+
+      #if BOTH(CUSTOM_BOOTSCREEN_ANIMATED, CUSTOM_BOOTSCREEN_TIME_PER_FRAME)
+        const boot_frame_t * const frame_info = (boot_frame_t*)frame_ptr;
+        const u8g_pgm_uint8_t * const bmp = (u8g_pgm_uint8_t*)pgm_read_ptr(&frame_info->bitmap);
+      #else
+        const u8g_pgm_uint8_t * const bmp = TERN(CUSTOM_BOOTSCREEN_ANIMATED, (u8g_pgm_uint8_t*)frame_ptr, custom_start_bmp);
+      #endif
+
       UNUSED(frame);
 
       u8g.drawBitmapP(left, top, CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH, CUSTOM_BOOTSCREEN_BMPHEIGHT, bmp);
@@ -141,22 +143,23 @@ bool MarlinUI::detected() { return true; }
     // Shows the custom bootscreen, with the u8g loop, animations and delays
     void MarlinUI::show_custom_bootscreen() {
       #if DISABLED(CUSTOM_BOOTSCREEN_ANIMATED)
-        constexpr millis_t d = 0;
+        constexpr millis_t frame_time = 0;
         constexpr uint8_t f = 0;
       #else
-        #if DISABLED(CUSTOM_BOOTSCREEN_ANIMATED_FRAME_TIME)
-          constexpr millis_t d = CUSTOM_BOOTSCREEN_FRAME_TIME;
+        #if DISABLED(CUSTOM_BOOTSCREEN_TIME_PER_FRAME)
+          constexpr millis_t frame_time = CUSTOM_BOOTSCREEN_FRAME_TIME;
         #endif
         LOOP_L_N(f, COUNT(custom_bootscreen_animation))
       #endif
         {
-          #if ENABLED(CUSTOM_BOOTSCREEN_ANIMATED_FRAME_TIME)
-            const uint8_t fr = _MIN(f, COUNT(custom_bootscreen_frame_time) - 1);
-            const millis_t d = custom_bootscreen_frame_time[fr];
+          #if ENABLED(CUSTOM_BOOTSCREEN_TIME_PER_FRAME)
+            const uint8_t fr = _MIN(f, COUNT(custom_bootscreen_animation) - 1);
+            const boot_frame_t * const frame_info = (boot_frame_t*)pgm_read_ptr(&custom_bootscreen_animation[fr]);
+            const millis_t frame_time = pgm_read_word(&frame_info->duration);
           #endif
           u8g.firstPage();
           do { draw_custom_bootscreen(f); } while (u8g.nextPage());
-          if (d) safe_delay(d);
+          if (frame_time) safe_delay(frame_time);
         }
 
       #ifndef CUSTOM_BOOTSCREEN_TIMEOUT
@@ -218,10 +221,10 @@ bool MarlinUI::detected() { return true; }
     #if DISABLED(BOOT_MARLIN_LOGO_ANIMATED)
       draw_bootscreen_bmp(start_bmp);
     #else
-      constexpr millis_t d = MARLIN_BOOTSCREEN_FRAME_TIME;
+      constexpr millis_t frame_time = MARLIN_BOOTSCREEN_FRAME_TIME;
       LOOP_L_N(f, COUNT(marlin_bootscreen_animation)) {
         draw_bootscreen_bmp((uint8_t*)pgm_read_ptr(&marlin_bootscreen_animation[f]));
-        if (d) safe_delay(d);
+        if (frame_time) safe_delay(frame_time);
       }
     #endif
   }