From 9e40449c649c6b839ac59979a9970a640fd602ee Mon Sep 17 00:00:00 2001 From: Alvin Wong Date: Mon, 3 May 2021 18:23:30 +0800 Subject: [PATCH 1/7] Add menu exit transition animation Part of which was removed in commit 04d72cb. --- source/Core/Src/gui.cpp | 109 +++++++++++++++++++----------- source/Core/Threads/GUIThread.cpp | 15 +++- 2 files changed, 82 insertions(+), 42 deletions(-) diff --git a/source/Core/Src/gui.cpp b/source/Core/Src/gui.cpp index 63eb711f..a24187d3 100644 --- a/source/Core/Src/gui.cpp +++ b/source/Core/Src/gui.cpp @@ -1034,6 +1034,18 @@ static bool settings_enterAdvancedMenu(void) { void gui_Menu(const menuitem *menu) { // Draw the settings menu and provide iteration support etc + + // This is used to detect whether a menu-exit transition should be played. + static bool wasInGuiMenu; + wasInGuiMenu = true; + + enum class NavState { + Idle, + Entering, + ScrollingDown, + Exiting, + }; + uint8_t currentScreen = 0; TickType_t autoRepeatTimer = 0; TickType_t autoRepeatAcceleration = 0; @@ -1043,7 +1055,7 @@ void gui_Menu(const menuitem *menu) { uint8_t scrollContentSize = 0; bool scrollBlink = false; bool lastValue = false; - bool scrollingDown = false; + NavState navState = NavState::Entering; ScrollMessage scrollMessage; @@ -1051,42 +1063,58 @@ void gui_Menu(const menuitem *menu) { scrollContentSize += 1; } - // Animated menu opening. - if (menu[currentScreen].draw != nullptr) { - // This menu is drawn in a secondary framebuffer. - // Then we play a transition from the current primary - // framebuffer to the new buffer. - // The extra buffer is discarded at the end of the transition. - animOpenState = true; - OLED::useSecondaryFramebuffer(true); - OLED::setCursor(0, 0); - OLED::clearScreen(); - menu[currentScreen].draw(); - OLED::useSecondaryFramebuffer(false); - OLED::transitionSecondaryFramebuffer(true); - animOpenState = false; - } - while ((menu[currentScreen].draw != nullptr) && earlyExit == false) { - OLED::setCursor(0, 0); - if (scrollingDown) { + + // Handle menu transition: + if (navState != NavState::Idle) { + // Check if this menu item shall be skipped. If it shall be skipped, + // `draw()` returns true. Draw on the secondary framebuffer as we want + // to keep the primary framebuffer intact for the upcoming transition + // animation. + OLED::useSecondaryFramebuffer(true); + if (menu[currentScreen].draw()) { + currentScreen++; + OLED::useSecondaryFramebuffer(false); + continue; + } + animOpenState = true; + // The menu entering/exiting transition uses the secondary framebuffer, + // but the scroll down transition does not. + if (navState == NavState::ScrollingDown) { + OLED::useSecondaryFramebuffer(false); + } + OLED::setCursor(0, 0); + OLED::clearScreen(); + menu[currentScreen].draw(); + if (navState == NavState::ScrollingDown) { + // Play the scroll down animation. + OLED::maskScrollIndicatorOnOLED(); + OLED::transitionScrollDown(); + } else { + // The menu was drawn in a secondary framebuffer. + // Now we play a transition from the pre-drawn primary + // framebuffer to the new buffer. + // The extra buffer is discarded at the end of the transition. + OLED::useSecondaryFramebuffer(false); + OLED::transitionSecondaryFramebuffer(navState == NavState::Entering); + } + animOpenState = false; + navState = NavState::Idle; } // If the user has hesitated for >=3 seconds, show the long text // Otherwise "draw" the option if ((xTaskGetTickCount() - lastButtonTime < (TICKS_SECOND * 3)) || menu[currentScreen].description == 0) { lcdRefresh = true; + OLED::setCursor(0, 0); OLED::clearScreen(); - if (menu[currentScreen].draw()) { - currentScreen++; - lcdRefresh = false; - } + menu[currentScreen].draw(); uint8_t indicatorHeight = OLED_HEIGHT / scrollContentSize; uint8_t position = OLED_HEIGHT * currentScreen / scrollContentSize; if (lastValue) scrollBlink = !scrollBlink; - if ((!lastValue || !scrollBlink) && !scrollingDown) + if (!lastValue || !scrollBlink) OLED::drawScrollIndicator(position, indicatorHeight); } else { // Draw description @@ -1095,15 +1123,8 @@ void gui_Menu(const menuitem *menu) { } if (lcdRefresh) { - if (scrollingDown) { - OLED::maskScrollIndicatorOnOLED(); - OLED::transitionScrollDown(); - scrollingDown = false; - animOpenState = false; - } else { - OLED::refresh(); // update the LCD - osDelay(40); - } + OLED::refresh(); // update the LCD + osDelay(40); lcdRefresh = false; } @@ -1114,6 +1135,16 @@ void gui_Menu(const menuitem *menu) { lastButtonState = buttons; } + auto callIncrementHandler = [&]() { + wasInGuiMenu = false; + bool res = menu[currentScreen].incrementHandler(); + if (wasInGuiMenu) { + navState = NavState::Exiting; + } + wasInGuiMenu = true; + return res; + }; + switch (buttons) { case BUTTON_BOTH: earlyExit = true; // will make us exit next loop @@ -1123,7 +1154,7 @@ void gui_Menu(const menuitem *menu) { // increment if (scrollMessage.isReset()) { if (menu[currentScreen].incrementHandler != nullptr) { - lastValue = menu[currentScreen].incrementHandler(); + lastValue = callIncrementHandler(); } else { earlyExit = true; } @@ -1133,14 +1164,14 @@ void gui_Menu(const menuitem *menu) { case BUTTON_B_SHORT: if (scrollMessage.isReset()) { currentScreen++; - scrollingDown = true; - lastValue = false; + navState = NavState::ScrollingDown; + lastValue = false; } else scrollMessage.reset(); break; case BUTTON_F_LONG: if (xTaskGetTickCount() + autoRepeatAcceleration > autoRepeatTimer + PRESS_ACCEL_INTERVAL_MAX) { - if ((lastValue = menu[currentScreen].incrementHandler())) + if ((lastValue = callIncrementHandler())) autoRepeatTimer = 1000; else autoRepeatTimer = 0; @@ -1155,7 +1186,7 @@ void gui_Menu(const menuitem *menu) { case BUTTON_B_LONG: if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { currentScreen++; - scrollingDown = true; + navState = NavState::ScrollingDown; autoRepeatTimer = xTaskGetTickCount(); scrollMessage.reset(); @@ -1178,8 +1209,6 @@ void gui_Menu(const menuitem *menu) { scrollMessage.reset(); } } - - animOpenState = false; } void enterSettingsMenu() { diff --git a/source/Core/Threads/GUIThread.cpp b/source/Core/Threads/GUIThread.cpp index 8437c4dc..ee9c935a 100644 --- a/source/Core/Threads/GUIThread.cpp +++ b/source/Core/Threads/GUIThread.cpp @@ -754,6 +754,7 @@ void startGUITask(void const *argument __unused) { bool buttonLockout = false; bool tempOnDisplay = false; bool tipDisconnectedDisplay = false; + bool showExitMenuTransition = false; { // Generate the flipped screen into ram for later use // flipped is generated by flipping each row @@ -820,6 +821,10 @@ void startGUITask(void const *argument __unused) { break; case BUTTON_B_SHORT: enterSettingsMenu(); // enter the settings menu + { + OLED::useSecondaryFramebuffer(true); + showExitMenuTransition = true; + } buttonLockout = true; break; default: @@ -921,7 +926,13 @@ void startGUITask(void const *argument __unused) { } } - OLED::refresh(); - GUIDelay(); + if (showExitMenuTransition) { + OLED::useSecondaryFramebuffer(false); + OLED::transitionSecondaryFramebuffer(false); + showExitMenuTransition = false; + } else { + OLED::refresh(); + GUIDelay(); + } } } From d9b0e7cf6b598178af413d9073f50a937a15d485 Mon Sep 17 00:00:00 2001 From: Alvin Wong Date: Mon, 3 May 2021 19:01:51 +0800 Subject: [PATCH 2/7] Draw menu icon even during a transition --- source/Core/Src/gui.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/source/Core/Src/gui.cpp b/source/Core/Src/gui.cpp index a24187d3..e56a2ca9 100644 --- a/source/Core/Src/gui.cpp +++ b/source/Core/Src/gui.cpp @@ -951,6 +951,8 @@ static bool settings_setHallEffect(void) { } #endif +// Indicates whether a menu transition is in progress, so that the menu icon +// animation is paused during the transition. static bool animOpenState = false; static void displayMenu(size_t index) { @@ -962,7 +964,6 @@ static void displayMenu(size_t index) { // 2 pixel wide scrolling indicator static TickType_t menuSwitchLoopTick = 0; static size_t menuCurrentIndex = sizeof(rootSettingsMenu) + 1; - static size_t currentFrame = 0; TickType_t step = TICKS_100MS * 5; switch (systemSettings.animationSpeed) { case settingOffSpeed_t::FAST: @@ -974,17 +975,25 @@ static void displayMenu(size_t index) { default: // SLOW or off - defaulted above break; } - if (!animOpenState) { + size_t currentFrame; + if (!animOpenState && systemSettings.animationSpeed != settingOffSpeed_t::OFF) { if (menuCurrentIndex != index) { menuCurrentIndex = index; - currentFrame = systemSettings.animationSpeed == settingOffSpeed_t::OFF ? 2 : 0; menuSwitchLoopTick = xTaskGetTickCount(); } - if (systemSettings.animationSpeed && (systemSettings.animationLoop || currentFrame != 2)) { - currentFrame = ((xTaskGetTickCount() - menuSwitchLoopTick) / step) % 3; + currentFrame = ((xTaskGetTickCount() - menuSwitchLoopTick) / step); + if (systemSettings.animationLoop) { + currentFrame %= 3; + } else if (currentFrame > 2) { + currentFrame = 2; } - OLED::drawArea(OLED_WIDTH - 16 - 2, 0, 16, 16, (&SettingsMenuIcons[index][(16 * 2) * currentFrame])); + } else { + // We want the animation to restart after completing the transition. + menuCurrentIndex = sizeof(rootSettingsMenu) + 1; + // Always draw the last frame if icon animation is disabled. + currentFrame = systemSettings.animationSpeed == settingOffSpeed_t::OFF ? 2 : 0; } + OLED::drawArea(OLED_WIDTH - 16 - 2, 0, 16, 16, (&SettingsMenuIcons[index][(16 * 2) * currentFrame])); } static bool settings_displayCalibrateVIN(void) { From 66c3edeaa077c4d7960cb5605d78ad91f79ee44a Mon Sep 17 00:00:00 2001 From: discip <53649486+discip@users.noreply.github.com> Date: Wed, 5 May 2021 00:05:15 +0200 Subject: [PATCH 3/7] Update translation_DE.json some minor updates --- Translations/translation_DE.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Translations/translation_DE.json b/Translations/translation_DE.json index 703e2b16..17d9ad6e 100644 --- a/Translations/translation_DE.json +++ b/Translations/translation_DE.json @@ -34,12 +34,12 @@ "zurückgesetzt!" ], "NoAccelerometerMessage": [ - "Kein Bewegungssensor", - "erkannt!" + "Bewegungssensor", + "nicht erkannt!" ], "NoPowerDeliveryMessage": [ - "Kein USB-PD IC", - "erkannt!" + "USB-PD IC", + "nicht erkannt!" ], "LockingKeysString": "GESPERRT", "UnlockingKeysString": "ENTSPERRT", @@ -219,7 +219,7 @@ "QCMaxVoltage": { "text2": [ "Spannungs-", - "grenze" + "obergrenze" ], "desc": "Maximal zulässige Spannung der verwendeten Spannungsversorgung " }, @@ -260,8 +260,8 @@ }, "HallEffSensitivity": { "text2": [ - "Hall-Sonde", - "Empfindlichkeit" + "Empfindlichkeit", + "der Hall-Sonde" ], "desc": "Empfindlichkeit der Hall-Sonde beim Erkennen des Ruhemodus " }, @@ -274,17 +274,17 @@ }, "MinVolCell": { "text2": [ - "Minimum", + "Minimale", "Spannung" ], - "desc": "Minimal zulässige Spannung pro Zelle <3S: 3,0V - 3,7V, 4/5/6S: 2,4V - 3,7V>" + "desc": "Minimal zulässige Spannung pro Zelle <3S: 3,0V - 3,7V | 4/5/6S: 2,4V - 3,7V>" }, "AnimLoop": { "text2": [ "Anim.", "Schleife" ], - "desc": "Icon-Animationen im Stammmenü wiederholen" + "desc": "Icon-Animationen im Hauptmenü wiederholen" }, "AnimSpeed": { "text2": [ @@ -298,18 +298,18 @@ "Leistungsimpulse", "Wartezeit" ], - "desc": "Dauer vor Abgabe von Wachhalteimpulsen (x 2,5s)" + "desc": "Dauer vor Abgabe von Wachhalteimpulsen " }, "PowerPulseDuration": { "text2": [ "Leistungsimpulse", "Dauer" ], - "desc": "Dauer des Wachhalteimpulses (x 250ms)" + "desc": "Dauer des Wachhalteimpulses " }, "LanguageSwitch": { "text2": [ - "Language:", + "Sprache:", " DE Deutsch" ], "desc": "" From d0d8bf98ece7eb143b7afcc144746d107e7fe388 Mon Sep 17 00:00:00 2001 From: discip <53649486+discip@users.noreply.github.com> Date: Wed, 5 May 2021 00:14:28 +0200 Subject: [PATCH 4/7] Update translation_DE.json --- Translations/translation_DE.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Translations/translation_DE.json b/Translations/translation_DE.json index 17d9ad6e..64f7839a 100644 --- a/Translations/translation_DE.json +++ b/Translations/translation_DE.json @@ -295,15 +295,15 @@ }, "PowerPulseWait": { "text2": [ - "Leistungsimpulse", + "Impuls", "Wartezeit" ], "desc": "Dauer vor Abgabe von Wachhalteimpulsen " }, "PowerPulseDuration": { "text2": [ - "Leistungsimpulse", - "Dauer" + "Impuls-", + "dauer" ], "desc": "Dauer des Wachhalteimpulses " }, From 4d3fa18f011ba7bbeea89befeba8f42dcc8fe786 Mon Sep 17 00:00:00 2001 From: discip <53649486+discip@users.noreply.github.com> Date: Wed, 5 May 2021 00:24:06 +0200 Subject: [PATCH 5/7] Update translation_DE.json --- Translations/translation_DE.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Translations/translation_DE.json b/Translations/translation_DE.json index 64f7839a..207786d8 100644 --- a/Translations/translation_DE.json +++ b/Translations/translation_DE.json @@ -128,7 +128,7 @@ "ShutdownTimeout": { "text2": [ "Abschalt-", - "zeit" + "verzögerung" ], "desc": "Dauer vor automatischer Abschaltung " }, @@ -226,7 +226,7 @@ "PowerLimit": { "text2": [ "Leistungs-", - "grenze" + "obergrenze" ], "desc": "Maximale zulässige Leistungsaufnahme des Lötkolbens " }, @@ -295,8 +295,8 @@ }, "PowerPulseWait": { "text2": [ - "Impuls", - "Wartezeit" + "Impuls-", + "verzögerung" ], "desc": "Dauer vor Abgabe von Wachhalteimpulsen " }, From 42dbe6346565495440f2dc489845af95775c0238 Mon Sep 17 00:00:00 2001 From: discip <53649486+discip@users.noreply.github.com> Date: Wed, 5 May 2021 00:42:49 +0200 Subject: [PATCH 6/7] Update translation_DE.json --- Translations/translation_DE.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Translations/translation_DE.json b/Translations/translation_DE.json index 207786d8..dce19913 100644 --- a/Translations/translation_DE.json +++ b/Translations/translation_DE.json @@ -15,7 +15,7 @@ "InputVoltageString": "V Eingang: ", "WarningTipTempString": "Temperatur: ", "BadTipString": "Spitze Defekt", - "SleepingSimpleString": "Zzz ", + "SleepingSimpleString": "Zzzz", "SleepingAdvancedString": "Ruhemodus...", "WarningSimpleString": "HEISS!", "WarningAdvancedString": "! Achtung Heiß !", @@ -128,7 +128,7 @@ "ShutdownTimeout": { "text2": [ "Abschalt-", - "verzögerung" + "verzög." ], "desc": "Dauer vor automatischer Abschaltung " }, @@ -219,14 +219,14 @@ "QCMaxVoltage": { "text2": [ "Spannungs-", - "obergrenze" + "maximum" ], "desc": "Maximal zulässige Spannung der verwendeten Spannungsversorgung " }, "PowerLimit": { "text2": [ "Leistungs-", - "obergrenze" + "maximum" ], "desc": "Maximale zulässige Leistungsaufnahme des Lötkolbens " }, From e3283a88a6633dc5065e4661c65fa2844911eade Mon Sep 17 00:00:00 2001 From: federicodilo <68966053+federicodilo@users.noreply.github.com> Date: Thu, 6 May 2021 09:20:29 +0200 Subject: [PATCH 7/7] Update translation_IT.json --- Translations/translation_IT.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Translations/translation_IT.json b/Translations/translation_IT.json index 45d9cc65..6070d4c5 100644 --- a/Translations/translation_IT.json +++ b/Translations/translation_IT.json @@ -218,7 +218,7 @@ "QCMaxVoltage": { "text2": [ "Voltaggio", - "Quick Charge" + "QC" ], "desc": "Imposta il massimo voltaggio negoziabile con un alimentatore Quick Charge" }, @@ -269,14 +269,14 @@ "Blocco", "tasti" ], - "desc": "Blocca i tasti durante la modalità Saldatura; tieni premuto entrambi per bloccare o sbloccare [D: disattiva; T: blocca Turbo; C: blocco completo]" + "desc": "Blocca i tasti durante la modalità Saldatura; tieni premuto entrambi per bloccare o sbloccare [D: disattiva; T: consenti Turbo; C: blocco completo]" }, "MinVolCell": { "text2": [ "Tensione", "min celle" ], - "desc": "Modifica il valore di tensione minima \"di scaricamento\" per le celle di una batteria Li-Po [3S: 3,0-3,7 V; 4S/5S/6S: 2,4-3,7 V]" + "desc": "Modifica la tensione di minima carica delle celle di una batteria Li-Po [3S: 3,0-3,7 V; 4S/5S/6S: 2,4-3,7 V]" }, "AnimLoop": { "text2": [ @@ -308,7 +308,7 @@ }, "LanguageSwitch": { "text2": [ - "Language:", + "Lingua:", " IT Italiano" ], "desc": ""