diff --git a/sketch/obd2_gauge/meter.h b/sketch/obd2_gauge/meter.h index 9275dcd..37446a8 100644 --- a/sketch/obd2_gauge/meter.h +++ b/sketch/obd2_gauge/meter.h @@ -1236,10 +1236,14 @@ void plotNoData(uint8_t cell) { } } -// Fast slide-frame rendering of Page 0 (4 Quadrants) shifted by x_offset +// Fast slide-frame rendering of Page 0 (4 Quadrants) shifted by x_offset (optimized for 60 FPS) inline void drawSlidePage0(int x_offset) { tft.fillRect(x_offset, 0, 320, 240, TFT_BLACK); + uint16_t bgCol = getThemeBgColor(); + uint16_t divCol = getThemeDivColor(); + uint16_t priCol = getThemePrimaryColor(); + // 4 Quadrants for (uint8_t c = 0; c < 4; c++) { int qx = cell4_x[c] + x_offset; @@ -1247,13 +1251,14 @@ inline void drawSlidePage0(int x_offset) { 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); + // Fast hardware fill for quadrant background + tft.fillRect(rx, ry, 159, 119, bgCol); - // Header PID icon uint8_t pidIdx = pidInCell[c]; - drawPidIcon(qx + 5, qy + 3, pidConfig[pidIdx][2]); + + // Fast header label in font 2 + tft.setTextColor(TFT_WHITE, bgCol); + tft.drawString(pidConfig[pidIdx][0].c_str(), qx + 8, qy + 6, 2); int warn = warningValue[pidIdx].toInt(); int min = pidConfig[pidIdx][4].toInt(); @@ -1262,7 +1267,7 @@ inline void drawSlidePage0(int x_offset) { float val = last_valid_data[c]; // Horizontal gauge bar - int barY = qy + 32; + int barY = qy + 28; tft.fillRoundRect(qx + 8, barY, 144, 6, 2, METER_INACTIVE_COLOR); if (val > -900.0f) { uint16_t col = getMeterColor(pidIdx, val, warn); @@ -1278,24 +1283,24 @@ inline void drawSlidePage0(int x_offset) { // 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.setTextColor(priCol, bgCol); tft.setTextPadding(114); - tft.drawRightString(numStr.c_str(), qx + 152, qy + 74, 1); + tft.drawRightString(numStr.c_str(), qx + 152, qy + 70, 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 +// Butter-smooth mobile slide transition with 14-frame ease-out deceleration inline void animateSlideTransition(bool swipeLeft) { touchBeep(); - const uint8_t FRAMES = 6; - const int16_t step_shifts[FRAMES] = { 54, 108, 162, 216, 270, 320 }; + const uint8_t FRAMES = 14; + // Cubic ease-out deceleration curve: fast initial departure, silk-smooth docking + const int16_t step_shifts[FRAMES] = { 38, 74, 108, 140, 170, 198, 224, 248, 268, 285, 298, 308, 316, 320 }; if (swipeLeft) { // SWIPE LEFT: Page 0 slides out to the left, Page 1 enters from the right @@ -1322,7 +1327,7 @@ inline void animateSlideTransition(bool swipeLeft) { tft.fillCircle(153, 2, 2, (splitX > 160) ? getThemePrimaryColor() : 0x5AEB); tft.fillCircle(167, 2, 2, (splitX <= 160) ? getThemePrimaryColor() : 0x5AEB); - delay(12); + delay(6); } } else { // SWIPE RIGHT: Page 1 slides out to the right, Page 0 enters from the left @@ -1349,7 +1354,7 @@ inline void animateSlideTransition(bool swipeLeft) { tft.fillCircle(153, 2, 2, (splitX >= 160) ? getThemePrimaryColor() : 0x5AEB); tft.fillCircle(167, 2, 2, (splitX < 160) ? getThemePrimaryColor() : 0x5AEB); - delay(12); + delay(6); } }