mirror of
https://github.com/Ralim/IronOS.git
synced 2025-02-26 07:53:55 +00:00
Simplified animation methods
This commit is contained in:
@@ -99,8 +99,7 @@ public:
|
|||||||
static void drawFilledRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
|
static void drawFilledRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
|
||||||
bool clear);
|
bool clear);
|
||||||
static void drawHeatSymbol(uint8_t state);
|
static void drawHeatSymbol(uint8_t state);
|
||||||
static void presentSecondScreenBufferAnimatedBack();
|
static void transitionToContents(uint8_t *framebuffer, bool forwardNavigation);
|
||||||
static void presentSecondScreenBufferAnimated();
|
|
||||||
static void set_framebuffer(uint8_t *buffer);
|
static void set_framebuffer(uint8_t *buffer);
|
||||||
private:
|
private:
|
||||||
static void drawChar(char c); // Draw a character to a specific location
|
static void drawChar(char c); // Draw a character to a specific location
|
||||||
|
|||||||
@@ -125,72 +125,49 @@ void OLED::drawChar(char c) {
|
|||||||
cursor_x += fontWidth;
|
cursor_x += fontWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OLED::presentSecondScreenBufferAnimatedBack() {
|
/**
|
||||||
uint8_t *firstBackStripPtr = &firstStripPtr[0];
|
* Plays a transition animation between two framebuffers.
|
||||||
uint8_t *secondBackStripPtr = &secondStripPtr[0];
|
* @param framebuffer Second framebuffer to use for animation.
|
||||||
set_framebuffer(NULL);
|
* @param forward Direction of the navigation animation.
|
||||||
|
*
|
||||||
|
* If forward is true, this displays a forward navigation to the second framebuffer contents.
|
||||||
|
* Otherwise a rewinding navigation animation is shown to the second framebuffer contents.
|
||||||
|
*/
|
||||||
|
void OLED::transitionToContents(uint8_t *framebuffer, bool forwardNavigation) {
|
||||||
|
uint8_t *firstBackStripPtr = &framebuffer[0];
|
||||||
|
uint8_t *secondBackStripPtr = &framebuffer[OLED_WIDTH];
|
||||||
|
|
||||||
uint32_t totalDuration = 50;
|
uint32_t totalDuration = 50; // 500ms
|
||||||
uint32_t duration = 0;
|
uint32_t duration = 0;
|
||||||
uint32_t start = xTaskGetTickCount();
|
uint32_t start = xTaskGetTickCount();
|
||||||
uint8_t offset = 0;
|
uint8_t offset = 0;
|
||||||
|
|
||||||
while (duration <= totalDuration) {
|
while (duration <= totalDuration) {
|
||||||
duration = xTaskGetTickCount() - start;
|
duration = xTaskGetTickCount() - start;
|
||||||
|
uint8_t progress = duration * 100 / totalDuration;
|
||||||
uint8_t progress = (duration * 100) / totalDuration;
|
|
||||||
progress = easeInOutTiming(progress);
|
progress = easeInOutTiming(progress);
|
||||||
progress = lerp(0, OLED_WIDTH, progress);
|
progress = lerp(0, OLED_WIDTH, progress);
|
||||||
if (progress > OLED_WIDTH) {
|
if (progress > OLED_WIDTH) {
|
||||||
progress = OLED_WIDTH;
|
progress = OLED_WIDTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
memmove(&firstStripPtr[progress], &firstStripPtr[offset], OLED_WIDTH - progress);
|
// When forward, current contents move to the left out.
|
||||||
memmove(&secondStripPtr[progress], &secondStripPtr[offset], OLED_WIDTH - progress);
|
// Otherwise the contents move to the right out.
|
||||||
|
uint8_t oldStart = forwardNavigation ? 0 : progress;
|
||||||
|
uint8_t oldPrevious = forwardNavigation ? progress - offset : offset;
|
||||||
|
|
||||||
|
// Content from the second framebuffer moves in from the right (forward)
|
||||||
|
// or from the left (not forward).
|
||||||
|
uint8_t newStart = forwardNavigation ? OLED_WIDTH - progress : 0;
|
||||||
|
uint8_t newEnd = forwardNavigation ? 0 : OLED_WIDTH - progress;
|
||||||
|
|
||||||
offset = progress;
|
offset = progress;
|
||||||
|
|
||||||
memmove(
|
|
||||||
&firstStripPtr[0],
|
|
||||||
&firstBackStripPtr[OLED_WIDTH - progress],
|
|
||||||
progress);
|
|
||||||
memmove(&secondStripPtr[0],
|
|
||||||
&secondBackStripPtr[OLED_WIDTH - progress],
|
|
||||||
progress);
|
|
||||||
|
|
||||||
refresh();
|
memmove(&firstStripPtr[oldStart], &firstStripPtr[oldPrevious], OLED_WIDTH - progress);
|
||||||
osDelay(40);
|
memmove(&secondStripPtr[oldStart], &secondStripPtr[oldPrevious], OLED_WIDTH - progress);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OLED::presentSecondScreenBufferAnimated() {
|
|
||||||
uint8_t *firstBackStripPtr = &firstStripPtr[0];
|
|
||||||
uint8_t *secondBackStripPtr = &secondStripPtr[0];
|
|
||||||
set_framebuffer(NULL);
|
|
||||||
|
|
||||||
uint32_t totalDuration = 50;
|
|
||||||
uint32_t duration = 0;
|
|
||||||
uint32_t start = xTaskGetTickCount();
|
|
||||||
uint8_t offset = 0;
|
|
||||||
while (duration < totalDuration) {
|
|
||||||
duration = xTaskGetTickCount() - start;
|
|
||||||
|
|
||||||
uint8_t progress = (duration * 100) / totalDuration;
|
memmove(&firstStripPtr[newStart], &firstBackStripPtr[newEnd], progress);
|
||||||
progress = easeInOutTiming(progress);
|
memmove(&secondStripPtr[newStart], &secondBackStripPtr[newEnd], progress);
|
||||||
progress = lerp(0, OLED_WIDTH, progress);
|
|
||||||
if (progress > OLED_WIDTH) {
|
|
||||||
progress = OLED_WIDTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
memmove(&firstStripPtr[0], &firstStripPtr[progress - offset], OLED_WIDTH - progress);
|
|
||||||
memmove(&secondStripPtr[0], &secondStripPtr[progress - offset], OLED_WIDTH - progress);
|
|
||||||
offset = progress;
|
|
||||||
|
|
||||||
memmove(
|
|
||||||
&firstStripPtr[OLED_WIDTH - progress],
|
|
||||||
&firstBackStripPtr[0],
|
|
||||||
progress);
|
|
||||||
memmove(&secondStripPtr[OLED_WIDTH - progress],
|
|
||||||
&secondBackStripPtr[0],
|
|
||||||
progress);
|
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
osDelay(40);
|
osDelay(40);
|
||||||
|
|||||||
@@ -826,14 +826,20 @@ void gui_Menu(const menuitem *menu) {
|
|||||||
static bool enterGUIMenu = true;
|
static bool enterGUIMenu = true;
|
||||||
enterGUIMenu = true;
|
enterGUIMenu = true;
|
||||||
|
|
||||||
|
// Animated menu opening.
|
||||||
if (menu[currentScreen].draw.func != NULL) {
|
if (menu[currentScreen].draw.func != NULL) {
|
||||||
uint8_t secondFrameBuffer[OLED_WIDTH * 2];
|
// This menu is drawn in a secondary framebuffer.
|
||||||
OLED::set_framebuffer(secondFrameBuffer);
|
// 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.
|
||||||
|
uint8_t secondaryFrameBuffer[OLED_WIDTH * 2];
|
||||||
|
OLED::set_framebuffer(secondaryFrameBuffer);
|
||||||
OLED::setFont(0);
|
OLED::setFont(0);
|
||||||
OLED::setCursor(0, 0);
|
OLED::setCursor(0, 0);
|
||||||
OLED::clearScreen();
|
OLED::clearScreen();
|
||||||
menu[currentScreen].draw.func();
|
menu[currentScreen].draw.func();
|
||||||
OLED::presentSecondScreenBufferAnimated();
|
OLED::set_framebuffer(NULL);
|
||||||
|
OLED::transitionToContents(secondaryFrameBuffer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((menu[currentScreen].draw.func != NULL) && earlyExit == false) {
|
while ((menu[currentScreen].draw.func != NULL) && earlyExit == false) {
|
||||||
@@ -888,13 +894,14 @@ void gui_Menu(const menuitem *menu) {
|
|||||||
menu[currentScreen].incrementHandler.func();
|
menu[currentScreen].incrementHandler.func();
|
||||||
|
|
||||||
if (enterGUIMenu) {
|
if (enterGUIMenu) {
|
||||||
uint8_t secondFrameBuffer[OLED_WIDTH * 2];
|
uint8_t secondaryFrameBuffer[OLED_WIDTH * 2];
|
||||||
OLED::set_framebuffer(secondFrameBuffer);
|
OLED::set_framebuffer(secondaryFrameBuffer);
|
||||||
OLED::setFont(0);
|
OLED::setFont(0);
|
||||||
OLED::setCursor(0, 0);
|
OLED::setCursor(0, 0);
|
||||||
OLED::clearScreen();
|
OLED::clearScreen();
|
||||||
menu[currentScreen].draw.func();
|
menu[currentScreen].draw.func();
|
||||||
OLED::presentSecondScreenBufferAnimatedBack();
|
OLED::set_framebuffer(NULL);
|
||||||
|
OLED::transitionToContents(secondaryFrameBuffer, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
earlyExit = true;
|
earlyExit = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user