diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp index bce39a6ec0d478c6492573961e46cc800995a800..ff954204c07ba01387cdaebc1aec7e905f5b39e8 100644 --- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp +++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/bed_mesh_screen.cpp @@ -43,41 +43,33 @@ using namespace ExtUI; #define GRID_COLS 5 #define GRID_ROWS 5 - #define MESH_POS BTN_POS(2,1), BTN_SIZE(4,5) - #define Z_LABEL_POS BTN_POS(1,3), BTN_SIZE(1,1) - #define Z_VALUE_POS BTN_POS(1,4), BTN_SIZE(2,1) - #define WAIT_POS BTN_POS(1,3), BTN_SIZE(2,2) - #define BACK_POS BTN_POS(1,5), BTN_SIZE(2,1) + #define MESH_POS BTN_POS(1,1), BTN_SIZE(3,5) + #define Z_LABEL_POS BTN_POS(4,2), BTN_SIZE(2,1) + #define Z_VALUE_POS BTN_POS(4,3), BTN_SIZE(2,1) + #define WAIT_POS BTN_POS(4,2), BTN_SIZE(2,2) + #define BACK_POS BTN_POS(4,5), BTN_SIZE(2,1) #endif -void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts) { - CommandProcessor cmd; +void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts, float autoscale_max) { + constexpr uint8_t rows = GRID_MAX_POINTS_Y; + constexpr uint8_t cols = GRID_MAX_POINTS_X; - #define TRANSFORM_2(X,Y,Z) (X), (Y) // No transform - #define TRANSFORM_1(X,Y,Z) TRANSFORM_2((X) + (Y) * slant, (Y) - (Z), 0) // Perspective - #define TRANSFORM(X,Y,Z) TRANSFORM_1(float(X)/(cols-1) - 0.5, float(Y)/(rows-1) - 0.5, (Z)) // Normalize + #define VALUE(X,Y) (data ? data[X][Y] : 0) + #define ISVAL(X,Y) (data ? !isnan(VALUE(X,Y)) : true) + #define HEIGHT(X,Y) (ISVAL(X,Y) ? (VALUE(X,Y) - val_min) * scale_z : 0) - constexpr uint8_t rows = GRID_MAX_POINTS_Y; - constexpr uint8_t cols = GRID_MAX_POINTS_X; - const float slant = 0.5; - const float bounds_min[] = {TRANSFORM(0 ,0 ,0)}; - const float bounds_max[] = {TRANSFORM(cols,rows,0)}; - const float scale_x = float(w)/(bounds_max[0] - bounds_min[0]); - const float scale_y = float(h)/(bounds_max[1] - bounds_min[1]); - const float center_x = x + w/2; - const float center_y = y + h/2; + // Compute the mean, min and max for the points float val_mean = 0; float val_max = -INFINITY; float val_min = INFINITY; uint8_t val_cnt = 0; - if (opts & USE_AUTOSCALE) { - // Compute the mean + if (data && (opts & USE_AUTOSCALE)) { for (uint8_t y = 0; y < rows; y++) { for (uint8_t x = 0; x < cols; x++) { - const float val = data[x][y]; - if (!isnan(val)) { + if (ISVAL(x,y)) { + const float val = VALUE(x,y); val_mean += val; val_max = max(val_max, val); val_min = min(val_min, val); @@ -85,27 +77,56 @@ void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI:: } } } - if (val_cnt) { - val_mean /= val_cnt; - val_min -= val_mean; - val_max -= val_mean; - } else { - val_mean = 0; - val_min = 0; - val_max = 0; - } } + if (val_cnt) { + val_mean /= val_cnt; + } else { + val_mean = 0; + val_min = 0; + val_max = 0; + } + + const float scale_z = ((val_max == val_min) ? 1 : 1/(val_max - val_min)) * autoscale_max; + + // These equations determine the appearance of the grid on the screen. + + #define TRANSFORM_5(X,Y,Z) (X), (Y) // No transform + #define TRANSFORM_4(X,Y,Z) TRANSFORM_5((X)/(Z),(Y)/-(Z), 0) // Perspective + #define TRANSFORM_3(X,Y,Z) TRANSFORM_4((X), (Z), (Y)) // Swap Z and Y + #define TRANSFORM_2(X,Y,Z) TRANSFORM_3((X), (Y) + 2.5, (Z) - 1) // Translate + #define TRANSFORM(X,Y,Z) TRANSFORM_2(float(X)/(cols-1) - 0.5, float(Y)/(rows-1) - 0.5, (Z)) // Normalize + + // Compute the bounding box for the grid prior to scaling. Do this at compile-time by + // transforming the four corner points via the transformation equations and finding + // the min and max for each axis. - const float scale_z = ((val_max == val_min) ? 1 : 1/(val_max - val_min)) * 0.1; + constexpr float bounds[][3] = {{TRANSFORM(0 , 0 , 0)}, + {TRANSFORM(cols-1, 0 , 0)}, + {TRANSFORM(0 , rows-1, 0)}, + {TRANSFORM(cols-1, rows-1, 0)}}; + #define APPLY(FUNC, AXIS) FUNC(FUNC(bounds[0][AXIS], bounds[1][AXIS]), FUNC(bounds[2][AXIS], bounds[3][AXIS])) + constexpr float grid_x = APPLY(min,0); + constexpr float grid_y = APPLY(min,1); + constexpr float grid_w = APPLY(max,0) - grid_x; + constexpr float grid_h = APPLY(max,1) - grid_y; + constexpr float grid_cx = grid_x + grid_w/2; + constexpr float grid_cy = grid_y + grid_h/2; - #undef TRANSFORM_2 - #define TRANSFORM_2(X,Y,Z) center_x + (X) * scale_x, center_y + (Y) * scale_y // Scale and position - #define VALUE(X,Y) ((data && ISVAL(X,Y)) ? data[X][Y] : 0) - #define ISVAL(X,Y) (data ? !isnan(data[X][Y]) : true) - #define HEIGHT(X,Y) (VALUE(X,Y) * scale_z) + // Figure out scale and offset such that the grid fits within the rectangle given by (x,y,w,h) - uint16_t basePointSize = min(scale_x,scale_y) / max(cols,rows); + const float scale_x = float(w)/grid_w; + const float scale_y = float(h)/grid_h; + const float center_x = x + w/2; + const float center_y = y + h/2; + #undef TRANSFORM_5 + #define TRANSFORM_5(X,Y,Z) center_x + (X - grid_cx) * scale_x, center_y + (Y - grid_cy) * scale_y // Fit to bounds + + // Draw the grid + + const uint16_t basePointSize = min(w,h) / max(cols,rows); + + CommandProcessor cmd; cmd.cmd(SAVE_CONTEXT()) .cmd(VERTEX_FORMAT(0)) .cmd(TAG_MASK(false)) @@ -126,13 +147,15 @@ void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI:: } if (opts & USE_POINTS) { + const float sq_min = sq(val_min - val_mean); + const float sq_max = sq(val_max - val_mean); cmd.cmd(POINT_SIZE(basePointSize * 2)); cmd.cmd(BEGIN(POINTS)); for (uint8_t x = 0; x < cols; x++) { if (ISVAL(x,y)) { if (opts & USE_COLORS) { const float val_dev = VALUE(x, y) - val_mean; - const uint8_t neg_byte = sq(val_dev) / sq(val_dev < 0 ? val_min : val_max) * 0xFF; + const uint8_t neg_byte = sq(val_dev) / (val_dev < 0 ? sq_min : sq_max) * 0xFF; const uint8_t pos_byte = 255 - neg_byte; cmd.cmd(COLOR_RGB(pos_byte, pos_byte, 0xFF)); } @@ -164,11 +187,12 @@ void BedMeshScreen::drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI:: if (opts & USE_HIGHLIGHT) { const uint8_t tag = screen_data.BedMeshScreen.highlightedTag; uint8_t x, y; - tagToPoint(tag, x, y); - cmd.cmd(COLOR_A(128)) - .cmd(POINT_SIZE(basePointSize * 6)) - .cmd(BEGIN(POINTS)) - .tag(tag).cmd(VERTEX2F(TRANSFORM(x, y, HEIGHT(x, y)))); + if (tagToPoint(tag, x, y)) { + cmd.cmd(COLOR_A(128)) + .cmd(POINT_SIZE(basePointSize * 6)) + .cmd(BEGIN(POINTS)) + .tag(tag).cmd(VERTEX2F(TRANSFORM(x, y, HEIGHT(x, y)))); + } } cmd.cmd(END()); cmd.cmd(RESTORE_CONTEXT()); @@ -178,9 +202,11 @@ uint8_t BedMeshScreen::pointToTag(uint8_t x, uint8_t y) { return y * (GRID_MAX_POINTS_X) + x + 10; } -void BedMeshScreen::tagToPoint(uint8_t tag, uint8_t &x, uint8_t &y) { +bool BedMeshScreen::tagToPoint(uint8_t tag, uint8_t &x, uint8_t &y) { + if (tag < 10) return false; x = (tag - 10) % (GRID_MAX_POINTS_X); y = (tag - 10) / (GRID_MAX_POINTS_X); + return true; } void BedMeshScreen::onEntry() { @@ -217,6 +243,9 @@ void BedMeshScreen::drawHighlightedPointValue() { } void BedMeshScreen::onRedraw(draw_mode_t what) { + #define _INSET_POS(x,y,w,h) x + min(w,h)/10, y + min(w,h)/10, w - min(w,h)/5, h - min(w,h)/5 + #define INSET_POS(pos) _INSET_POS(pos) + if (what & BACKGROUND) { CommandProcessor cmd; cmd.cmd(CLEAR_COLOR_RGB(bg_color)) @@ -224,16 +253,20 @@ void BedMeshScreen::onRedraw(draw_mode_t what) { // Draw the shadow and tags cmd.cmd(COLOR_RGB(0x444444)); - BedMeshScreen::drawMesh(MESH_POS, nullptr, USE_POINTS | USE_TAGS); + BedMeshScreen::drawMesh(INSET_POS(MESH_POS), nullptr, USE_POINTS | USE_TAGS); cmd.cmd(COLOR_RGB(bg_text_enabled)); } if (what & FOREGROUND) { + constexpr float autoscale_max_amplitude = 0.03; const bool levelingFinished = screen_data.BedMeshScreen.count >= GRID_MAX_POINTS; + const float levelingProgress = sq(float(screen_data.BedMeshScreen.count) / GRID_MAX_POINTS); if (levelingFinished) drawHighlightedPointValue(); - BedMeshScreen::drawMesh(MESH_POS, ExtUI::getMeshArray(), - USE_POINTS | USE_HIGHLIGHT | USE_AUTOSCALE | (levelingFinished ? USE_COLORS : 0)); + BedMeshScreen::drawMesh(INSET_POS(MESH_POS), ExtUI::getMeshArray(), + USE_POINTS | USE_HIGHLIGHT | USE_AUTOSCALE | (levelingFinished ? USE_COLORS : 0), + autoscale_max_amplitude * levelingProgress + ); } } @@ -243,7 +276,7 @@ bool BedMeshScreen::onTouchStart(uint8_t tag) { } bool BedMeshScreen::onTouchEnd(uint8_t tag) { - switch(tag) { + switch (tag) { case 1: GOTO_PREVIOUS(); return true; diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/boot_screen.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/boot_screen.cpp index 5e022b58e73de2044854e1fe3b4ffaf809bcc416..fcb0b67f88b1bb3940d79fa338151cac56583876 100644 --- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/boot_screen.cpp +++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/boot_screen.cpp @@ -68,10 +68,10 @@ void BootScreen::onIdle() { InterfaceSettingsScreen::failSafeSettings(); StatusScreen::loadBitmaps(); + StatusScreen::setStatusMessage(GET_TEXT_F(WELCOME_MSG)); GOTO_SCREEN(TouchCalibrationScreen); current_screen.forget(); PUSH_SCREEN(StatusScreen); - StatusScreen::setStatusMessage(GET_TEXT_F(WELCOME_MSG)); } else { if (!UIFlashStorage::is_valid()) { StatusScreen::loadBitmaps(); diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h index 8fa4800d6a8ae6f87ea3da85007b69567168dc87..06f64d38cb67c3f184248b3a3b47f66c8ab8d87e 100644 --- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h +++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h @@ -145,10 +145,10 @@ class BedMeshScreen : public BaseScreen, public CachedScreen<BED_MESH_SCREEN_CAC }; static uint8_t pointToTag(uint8_t x, uint8_t y); - static void tagToPoint(uint8_t tag, uint8_t &x, uint8_t &y); + static bool tagToPoint(uint8_t tag, uint8_t &x, uint8_t &y); static float getHightlightedValue(); static void drawHighlightedPointValue(); - static void drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts); + static void drawMesh(int16_t x, int16_t y, int16_t w, int16_t h, ExtUI::bed_mesh_t data, uint8_t opts, float autoscale_max = 0.1); public: static void onMeshUpdate(const int8_t x, const int8_t y, const float val); diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/status_screen.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/status_screen.cpp index 98d0bba75941080849c8a5fae8a3e059f42f43c4..816f6986f5789dfd4a6080e53940ed9db7975cb5 100644 --- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/status_screen.cpp +++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/status_screen.cpp @@ -272,8 +272,8 @@ void StatusScreen::draw_interaction_buttons(draw_mode_t what) { CommandProcessor cmd; cmd.colors(normal_btn) .font(Theme::font_medium) - .enabled(has_media) .colors(has_media ? action_btn : normal_btn) + .enabled(has_media) .tag(3).button(MEDIA_BTN_POS, isPrintingFromMedia() ? GET_TEXT_F(MSG_PRINTING) : GET_TEXT_F(MSG_BUTTON_MEDIA)) .colors(!has_media ? action_btn : normal_btn) .tag(4).button( MENU_BTN_POS, GET_TEXT_F(MSG_BUTTON_MENU)); @@ -360,6 +360,7 @@ void StatusScreen::onRedraw(draw_mode_t what) { } void StatusScreen::onEntry() { + BaseScreen::onEntry(); onRefresh(); } diff --git a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/touch_calibration_screen.cpp b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/touch_calibration_screen.cpp index b6c5ecae3d85b45f9054e50752f95e62ec111d61..3520836bb87f6d022504566c5b8839a0348a0d95 100644 --- a/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/touch_calibration_screen.cpp +++ b/Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/touch_calibration_screen.cpp @@ -32,6 +32,8 @@ using namespace Theme; #define GRID_COLS 4 #define GRID_ROWS 16 +#define TEXT_POS BTN_POS(1,1), BTN_SIZE(4,12) + void TouchCalibrationScreen::onEntry() { CommandProcessor cmd; @@ -45,7 +47,7 @@ void TouchCalibrationScreen::onEntry() { .cmd(CLEAR_COLOR_RGB(bg_color)) .cmd(CLEAR(true,true,true)) .cmd(COLOR_RGB(bg_text_enabled)); - draw_text_box(cmd, BTN_POS(1,1), BTN_SIZE(4,16), GET_TEXT_F(MSG_TOUCH_CALIBRATION_START), OPT_CENTER, font_large); + draw_text_box(cmd, TEXT_POS, GET_TEXT_F(MSG_TOUCH_CALIBRATION_START), OPT_CENTER, font_large); cmd.cmd(DL::DL_DISPLAY) .cmd(CMD_SWAP) .execute(); @@ -76,7 +78,7 @@ void TouchCalibrationScreen::onRedraw(draw_mode_t) { .cmd(CLEAR(true,true,true)) .cmd(COLOR_RGB(bg_text_enabled)); - draw_text_box(cmd, BTN_POS(1,1), BTN_SIZE(4,16), GET_TEXT_F(MSG_TOUCH_CALIBRATION_PROMPT), OPT_CENTER, font_large); + draw_text_box(cmd, TEXT_POS, GET_TEXT_F(MSG_TOUCH_CALIBRATION_PROMPT), OPT_CENTER, font_large); cmd.cmd(CMD_CALIBRATE); }