feat(ui): implementar traslacion fisica completa de pantallas en transicion deslizante
This commit is contained in:
parent
b932c9e298
commit
15571db86a
2 changed files with 127 additions and 26 deletions
|
|
@ -1236,6 +1236,126 @@ void plotNoData(uint8_t cell) {
|
|||
}
|
||||
}
|
||||
|
||||
// Fast slide-frame rendering of Page 0 (4 Quadrants) shifted by x_offset
|
||||
inline void drawSlidePage0(int x_offset) {
|
||||
tft.fillRect(x_offset, 0, 320, 240, TFT_BLACK);
|
||||
|
||||
// 4 Quadrants
|
||||
for (uint8_t c = 0; c < 4; c++) {
|
||||
int qx = cell4_x[c] + x_offset;
|
||||
int qy = cell4_y[c];
|
||||
int rx = (c & 1) ? (161 + x_offset) : (0 + x_offset);
|
||||
int ry = (c & 2) ? 121 : 0;
|
||||
|
||||
// Ambient vignette gradient
|
||||
tft.fillRectVGradient(rx, ry, 159, 82, getThemeBgColor(), TFT_BLACK);
|
||||
tft.fillRect(rx, ry + 82, 159, 37, TFT_BLACK);
|
||||
|
||||
// Header PID icon
|
||||
uint8_t pidIdx = pidInCell[c];
|
||||
drawPidIcon(qx + 5, qy + 3, pidConfig[pidIdx][2]);
|
||||
|
||||
int warn = warningValue[pidIdx].toInt();
|
||||
int min = pidConfig[pidIdx][4].toInt();
|
||||
int max = pidConfig[pidIdx][5].toInt();
|
||||
bool digit = pidConfig[pidIdx][7].toInt();
|
||||
float val = last_valid_data[c];
|
||||
|
||||
// Horizontal gauge bar
|
||||
int barY = qy + 32;
|
||||
tft.fillRoundRect(qx + 8, barY, 144, 6, 2, METER_INACTIVE_COLOR);
|
||||
if (val > -900.0f) {
|
||||
uint16_t col = getMeterColor(pidIdx, val, warn);
|
||||
float ratio = (val - (float)min) / (float)(max - min);
|
||||
if (ratio < 0.0f) ratio = 0.0f;
|
||||
if (ratio > 1.0f) ratio = 1.0f;
|
||||
int fillW = (int)(ratio * 144.0f);
|
||||
if (fillW < 4) fillW = 4;
|
||||
if (fillW > 144) fillW = 144;
|
||||
tft.fillRoundRect(qx + 8, barY, fillW, 6, 2, col);
|
||||
}
|
||||
|
||||
// Digital value using DSEG7 Modern 34pt
|
||||
String numStr = (val <= -900.0f) ? "---" : String(val, digit);
|
||||
tft.loadFont(DSEG7_Modern_BoldItalic_34);
|
||||
tft.setTextColor(getThemePrimaryColor(), TFT_BLACK);
|
||||
tft.setTextPadding(114);
|
||||
tft.drawRightString(numStr.c_str(), qx + 152, qy + 74, 1);
|
||||
tft.setTextPadding(0);
|
||||
tft.unloadFont();
|
||||
}
|
||||
|
||||
// Crosshair dividers
|
||||
uint16_t divCol = getThemeDivColor();
|
||||
tft.fillRect(159 + x_offset, 0, 2, 240, divCol);
|
||||
tft.fillRect(x_offset, 119, 320, 2, divCol);
|
||||
}
|
||||
|
||||
// True physical mobile-like slide transition: both screens visibly move across the glass
|
||||
inline void animateSlideTransition(bool swipeLeft) {
|
||||
touchBeep();
|
||||
const uint8_t FRAMES = 6;
|
||||
const int16_t step_shifts[FRAMES] = { 54, 108, 162, 216, 270, 320 };
|
||||
|
||||
if (swipeLeft) {
|
||||
// SWIPE LEFT: Page 0 slides out to the left, Page 1 enters from the right
|
||||
for (uint8_t f = 0; f < FRAMES; f++) {
|
||||
int16_t shift = step_shifts[f];
|
||||
int16_t splitX = 320 - shift;
|
||||
|
||||
if (splitX > 0) {
|
||||
tft.setViewport(0, 0, splitX, 240, false);
|
||||
drawSlidePage0(-shift);
|
||||
}
|
||||
|
||||
if (splitX < 320) {
|
||||
tft.setViewport(splitX, 0, 320 - splitX, 240, false);
|
||||
drawSlidePage1(splitX);
|
||||
}
|
||||
|
||||
tft.resetViewport();
|
||||
if (splitX > 0 && splitX < 320) {
|
||||
tft.drawFastVLine(splitX, 0, 240, getThemePrimaryColor());
|
||||
tft.drawFastVLine(splitX + 1, 0, 240, TFT_WHITE);
|
||||
}
|
||||
|
||||
tft.fillCircle(153, 2, 2, (splitX > 160) ? getThemePrimaryColor() : 0x5AEB);
|
||||
tft.fillCircle(167, 2, 2, (splitX <= 160) ? getThemePrimaryColor() : 0x5AEB);
|
||||
|
||||
delay(12);
|
||||
}
|
||||
} else {
|
||||
// SWIPE RIGHT: Page 1 slides out to the right, Page 0 enters from the left
|
||||
for (uint8_t f = 0; f < FRAMES; f++) {
|
||||
int16_t shift = step_shifts[f];
|
||||
int16_t splitX = shift;
|
||||
|
||||
if (splitX > 0) {
|
||||
tft.setViewport(0, 0, splitX, 240, false);
|
||||
drawSlidePage0(splitX - 320);
|
||||
}
|
||||
|
||||
if (splitX < 320) {
|
||||
tft.setViewport(splitX, 0, 320 - splitX, 240, false);
|
||||
drawSlidePage1(splitX);
|
||||
}
|
||||
|
||||
tft.resetViewport();
|
||||
if (splitX > 0 && splitX < 320) {
|
||||
tft.drawFastVLine(splitX, 0, 240, getThemePrimaryColor());
|
||||
tft.drawFastVLine(splitX - 1, 0, 240, TFT_WHITE);
|
||||
}
|
||||
|
||||
tft.fillCircle(153, 2, 2, (splitX >= 160) ? getThemePrimaryColor() : 0x5AEB);
|
||||
tft.fillCircle(167, 2, 2, (splitX < 160) ? getThemePrimaryColor() : 0x5AEB);
|
||||
|
||||
delay(12);
|
||||
}
|
||||
}
|
||||
|
||||
tft.resetViewport();
|
||||
}
|
||||
|
||||
/*-------------------*/
|
||||
// initialize display
|
||||
void initScreen() {
|
||||
|
|
|
|||
|
|
@ -220,30 +220,11 @@ inline void updateTriTempSensors(bool forceRedraw = false) {
|
|||
}
|
||||
}
|
||||
|
||||
// Animated mobile-like slide transition between screens
|
||||
inline void animateSlideTransition(bool swipeLeft) {
|
||||
touchBeep();
|
||||
const uint8_t STEPS = 10;
|
||||
const uint16_t STEP_W = 320 / STEPS; // 32 px
|
||||
uint16_t primary = getThemePrimaryColor();
|
||||
// Draw fast slide frame of Page 1 (3 temperature cards) shifted by x_offset
|
||||
inline void drawSlidePage1(int x_offset) {
|
||||
tft.fillRect(x_offset, 0, 320, 240, TFT_BLACK);
|
||||
drawTriTempCard(0, tempEngineCoolant, x_offset);
|
||||
drawTriTempCard(1, tempInterior, x_offset);
|
||||
drawTriTempCard(2, tempExterior, x_offset);
|
||||
}
|
||||
|
||||
if (swipeLeft) {
|
||||
// Swipe left: wipe beam sweeping from right to left
|
||||
for (int s = 0; s < STEPS; s++) {
|
||||
int x = 320 - (s + 1) * STEP_W;
|
||||
tft.fillRect(x, 0, STEP_W, 240, TFT_BLACK);
|
||||
tft.drawFastVLine(x, 0, 240, primary);
|
||||
tft.drawFastVLine(x + 1, 0, 240, TFT_WHITE);
|
||||
delay(10);
|
||||
}
|
||||
} else {
|
||||
// Swipe right: wipe beam sweeping from left to right
|
||||
for (int s = 0; s < STEPS; s++) {
|
||||
int x = s * STEP_W;
|
||||
tft.fillRect(x, 0, STEP_W, 240, TFT_BLACK);
|
||||
tft.drawFastVLine(x + STEP_W - 1, 0, 240, primary);
|
||||
tft.drawFastVLine(x + STEP_W - 2, 0, 240, TFT_WHITE);
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue