From ccd8911af086106d897db76480c63a5026a5a02b Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Wed, 29 Jul 2026 16:45:18 +0200 Subject: [PATCH 01/12] Add structural compile-time safety guards for BED_MESH_VIEWER --- Marlin/src/core/sanitycheck.h | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Marlin/src/core/sanitycheck.h diff --git a/Marlin/src/core/sanitycheck.h b/Marlin/src/core/sanitycheck.h new file mode 100644 index 000000000000..e902c41c48d4 --- /dev/null +++ b/Marlin/src/core/sanitycheck.h @@ -0,0 +1,8 @@ +#if ENABLED(BED_MESH_VIEWER) + #if !HAS_MARLINUI_U8GLIB + #error "BED_MESH_VIEWER requires a graphical LCD compatible with U8glib (e.g., MINI12864)." + #endif + #if !HAS_LEVELING + #error "BED_MESH_VIEWER requires at least one leveling system enabled (MESH, BILINEAR, or UBL)." + #endif +#endif \ No newline at end of file From 8a70c225a6c2b85b0c42e712b076039dcb8c42c6 Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Wed, 29 Jul 2026 16:46:43 +0200 Subject: [PATCH 02/12] LCD: Add menu_bed_mesh.cpp for real-time 2D grid typography map Introduced the core implementation file for BED_MESH_VIEWER. It provides a pixel-optimized 2D stationary-barycentric visual layout and real-time numeric scale feedback (with automatic font downscaling and background inversion for negative values) tailored for standard 12864 U8glib monochrome LCDs. --- Marlin/src/lcd/dogm/menu_bed_mesh.cpp | 385 ++++++++++++++++++++++++++ 1 file changed, 385 insertions(+) create mode 100644 Marlin/src/lcd/dogm/menu_bed_mesh.cpp diff --git a/Marlin/src/lcd/dogm/menu_bed_mesh.cpp b/Marlin/src/lcd/dogm/menu_bed_mesh.cpp new file mode 100644 index 000000000000..470481007b48 --- /dev/null +++ b/Marlin/src/lcd/dogm/menu_bed_mesh.cpp @@ -0,0 +1,385 @@ +#include "../../inc/MarlinConfig.h" + +#if HAS_MARLINUI_U8GLIB && ENABLED(BED_MESH_VIEWER) + +#include "../marlinui.h" +#include "marlinui_DOGM.h" + +// Official header to expose the 'bedlevel' (mesh_bed_leveling) class instance +#include "../../feature/bedlevel/bedlevel.h" + +#define MESH_MAP_COLS _MIN(GRID_MAX_POINTS_X, 7) +#define MESH_MAP_ROWS _MIN(GRID_MAX_POINTS_Y, 7) + +static int16_t static_micron_values[7][7]; +static bool view_mode_numeric = false; +static bool view_mode_help = false; // Flag to activate the full-screen exclusive Help Screen +static uint8_t selected_button = 1; // 1 = VIS, 2 = INFO, 3 = ESC + +void menu_bed_mesh_draw(); + +// 1. UNIVERSAL INITIALIZATION COMPATIBLE WITH ALL LEVELING SYSTEMS +void menu_bed_mesh_init() { + selected_button = 1; + view_mode_numeric = false; + view_mode_help = false; + + for (uint8_t x = 0; x < 7; x++) { + for (uint8_t y = 0; y < 7; y++) { + static_micron_values[x][y] = 0; + } + } + + // Safe data extraction using official Marlin leveling structures + for (uint8_t x = 0; x < MESH_MAP_COLS; x++) { + for (uint8_t y = 0; y < MESH_MAP_ROWS; y++) { + float z = 0.0; + + #if ENABLED(MESH_BED_LEVELING) + z = bedlevel.z_values[x][y]; + #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) + #if defined(bilinear_grid_values) + z = bilinear_grid_values[x][y]; + #elif HAS_LEVELING + z = bedlevel.z_values[x][y]; + #endif + #elif ENABLED(AUTO_BED_LEVELING_UBL) + z = ubl.z_values[x][y]; + #endif + + if (!isnan(z) && z > -10.0 && z < 10.0) { + static_micron_values[x][y] = (int16_t)(z * 1000.0); + } + } + } + + ui.encoderPosition = 0; + + // EXCLUSIVE SCREEN LOOP WITH RELATIVE ENCODER TRACKING + bool in_mesh_screen = true; + int16_t last_encoder_pos = 0; + + while (in_mesh_screen) { + ui.update(); // Poll hardware pins on the mainboard + + const int16_t current_encoder_pos = ui.encoderPosition; + if (current_encoder_pos != last_encoder_pos) { + int16_t diff = current_encoder_pos - last_encoder_pos; + + // If inside the Help Screen, any knob rotation closes it + if (view_mode_help) { + view_mode_help = false; + ui.encoderPosition = 0; + last_encoder_pos = 0; + } + else { + if (diff > 0) { + selected_button = (selected_button % 3) + 1; + } + else if (diff < 0) { + selected_button = (selected_button == 1) ? 3 : selected_button - 1; + } + last_encoder_pos = current_encoder_pos; + } + ui.refresh(); + } + + if (ui.use_click()) { + // If clicked while inside the Help Screen, close it immediately + if (view_mode_help) { + view_mode_help = false; + } + else { + if (selected_button == 1) { + view_mode_numeric = !view_mode_numeric; + } + else if (selected_button == 2) { + view_mode_help = true; // Activate full-screen textless infographic help mode + } + else if (selected_button == 3) { + in_mesh_screen = false; // Exit back to Marlin menu structure + } + } + ui.refresh(); + } + + u8g.firstPage(); + do { + menu_bed_mesh_draw(); + } while (u8g.nextPage()); + + safe_delay(20); + } + + ui.goto_previous_screen(); +} + +// 2. GRAPHICAL RENDERING FUNCTION +void menu_bed_mesh_draw() { + + if (view_mode_help) { + // ========================================================================= + // UNIVERSAL INFOGRAPHIC HELP SCREEN (TEXTLESS / FULL SCREEN) + // ========================================================================= + + // 1. DRAW BED LATERAL SECTION VIEW (LEFT SIDE) + // Dashed baseline representing Z = 0 (Ideal flat bed) + for (int x = 6; x < 50; x += 3) u8g.drawHLine(x, 26, 1); + + // Warped bed profile: positive peak (convex) and negative lake (concave) using smooth segments + u8g.drawLine(6, 26, 10, 18); + u8g.drawLine(10, 18, 16, 14); + u8g.drawLine(16, 14, 22, 18); + u8g.drawLine(22, 18, 26, 26); + + u8g.drawLine(26, 26, 30, 34); + u8g.drawLine(30, 34, 36, 38); + u8g.drawLine(36, 38, 42, 34); + u8g.drawLine(42, 34, 46, 26); + + // Connecting arrows linking bed profile anomalies to the right-side layout examples + u8g.drawLine(18, 10, 75, 10); u8g.drawPixel(18, 11); u8g.drawPixel(18, 12); // High indicator + u8g.drawLine(38, 42, 75, 42); u8g.drawPixel(38, 41); u8g.drawPixel(38, 40); // Low indicator + + // 2. GRAPHICAL MESH PATTERN EXAMPLES (RIGHT SIDE) + const int ex_pos_center_x = 80; + const int ex_neg_center_x = 80; + const int ex_pos_center_y = 14; + const int ex_neg_center_y = 42; + + // High Example (Top): Convex point -> expansion from stational center (8-pixel sample) + u8g.drawPixel(ex_pos_center_x, ex_pos_center_y); + const int8_t ex_path_pos_x[] = { 0, 1, 0, -1, 1, 1, -1, -1 }; + const int8_t ex_path_pos_y[] = { -1, 0, 1, 0, -1, 1, 1, -1 }; + for (int i = 0; i < 8; i++) u8g.drawPixel(ex_pos_center_x + ex_path_pos_x[i], ex_pos_center_y + ex_path_pos_y[i]); + + // Low Example (Bottom): Concave point -> 9x9 frame bounding a symmetrical collapse (8-pixel sample) + u8g.drawFrame(ex_neg_center_x - 4, ex_neg_center_y - 4, 9, 9); + const int8_t ex_path_neg_x[] = { -3, -3, 3, 3, -2, -3, -3, -2 }; + const int8_t ex_path_neg_y[] = { -3, 3, 3, -3, -3, -2, 2, 3 }; + for (int i = 0; i < 8; i++) u8g.drawPixel(ex_neg_center_x + ex_path_neg_x[i], ex_neg_center_y + ex_path_neg_y[i]); + + // 3. DYNAMIC MATHEMATICAL SCALE FORMULA DISPLAY (BOTTOM LEFT) + #ifdef MESH_EDIT_Z_STEP + const int16_t step_micron = (int16_t)(MESH_EDIT_Z_STEP * 1000.0); + #else + const int16_t step_micron = 25; + #endif + + char step_buf[6]; + itoa(step_micron, step_buf, 10); + + u8g.setFont(u8g_font_5x7); + u8g.drawStr(6, 60, "1 Px ="); + u8g.drawStr(44, 60, step_buf); + + // Pixel-by-pixel micro-drawing of the micro symbol 'µm' due to lack of character map support on basic LCD fonts + int label_offset_x = 44 + (strlen(step_buf) * 6); + u8g.drawVLine(label_offset_x, 56, 4); // Left leg + u8g.drawVLine(label_offset_x + 2, 56, 4); // Right leg + u8g.drawHLine(label_offset_x, 59, 3); // Bottom join + u8g.drawPixel(label_offset_x - 1, 59); // Entry tick + u8g.drawStr(label_offset_x + 4, 60, "m"); // Appends final 'm' + + // 4. INTERNATIONAL VERTICAL EXIT COMBINED ICON STRUCTURE (BOTTOM RIGHT) + const int exit_x = 112; + + // Encoder knob glyph + u8g.drawCircle(exit_x, 6, 4); + u8g.drawPixel(exit_x, 6); + + // Press arrow glyph + u8g.drawVLine(exit_x, 14, 5); + u8g.drawPixel(exit_x - 1, 17); u8g.drawPixel(exit_x + 1, 17); + u8g.drawPixel(exit_x - 2, 16); u8g.drawPixel(exit_x + 2, 16); + + u8g.setFont(u8g_font_5x7); + u8g.drawStr(exit_x - 14, 29, "CLICK"); + + // Open door exit glyph + const int door_x = exit_x - 8; + const int door_y = 38; + + u8g.drawVLine(door_x, door_y, 16); + u8g.drawHLine(door_x, door_y, 12); + u8g.drawVLine(door_x + 12, door_y, 16); + + u8g.drawLine(door_x, door_y, door_x - 4, door_y + 4); + u8g.drawVLine(door_x - 4, door_y + 4, 16); + u8g.drawLine(door_x - 4, door_y + 20, door_x, door_y + 16); + + u8g.drawHLine(door_x + 3, door_y + 9, 13); + u8g.drawPixel(door_x + 14, door_y + 8); + u8g.drawPixel(door_x + 14, door_y + 10); + u8g.drawPixel(door_x + 13, door_y + 7); + u8g.drawPixel(door_x + 13, door_y + 11); + + return; // Fast return to block standard view layers + } + + // ========================================================================= + // STANDARD LAYOUT LAYER (GRID + ACTION SIDEBAR) + // ========================================================================= + if (view_mode_numeric) { + // ========================================================================= + // MODAL NUMERIC VIEW WITH ADAPTIVE ANTI-OVERLAP BOUNDS (FULL WIDTH) + // ========================================================================= + + // Uses full left screen width (100px) - grid spacing adjusts per column count + const int num_x_spacing = 100 / MESH_MAP_COLS; // Evaluates to 14px for 7x7/6x6, and 20px for 5x5 + const int num_y_spacing = 54 / MESH_MAP_ROWS; + + const int start_num_x = (100 - (MESH_MAP_COLS * num_x_spacing)) / 2; + const int start_num_y = (64 - (MESH_MAP_ROWS * num_y_spacing)) / 2; + + // Dynamic font assignment to prevent overlapping on high density meshes (6x6 and 7x7) + int char_w = 5; + int char_h = 7; + if (MESH_MAP_COLS > 5) { + u8g.setFont(u8g_font_4x6); // Ultra-compact 4px width font for 6x6 and 7x7 meshes + char_w = 4; + char_h = 6; + } else { + u8g.setFont(u8g_font_5x7); // Standard 5px width font for meshes up to 5x5 + char_w = 5; + char_h = 7; + } + + for (uint8_t x = 0; x < MESH_MAP_COLS; x++) { + for (uint8_t y = 0; y < MESH_MAP_ROWS; y++) { + int16_t micron_val = static_micron_values[x][y]; + + int cell_center_x = start_num_x + (x * num_x_spacing) + (num_x_spacing / 2); + int draw_y = start_num_y + ((MESH_MAP_ROWS - 1 - y) * num_y_spacing) + char_h + 1; + + char buf[6]; + + if (micron_val == 0) { + u8g.drawStr(cell_center_x - (char_w / 2), draw_y, "0"); + } + else if (micron_val < 0) { + // --- NEGATIVE VALUE (Dark text printed over tight white solid box) --- + micron_val = -micron_val; + itoa(micron_val, buf, 10); + + int text_len = strlen(buf); + int text_width = text_len * char_w + (text_len - 1); + int draw_x = cell_center_x - (text_width / 2); + + // Draws white bounding box tailored to the currently active font geometry + u8g.drawBox(draw_x - 1, draw_y - char_h, text_width + 2, char_h + 2); + + u8g.setColorIndex(0); + u8g.drawStr(draw_x, draw_y, buf); + u8g.setColorIndex(1); + } + else { + // --- POSITIVE VALUE (Standard bright text centered layout) --- + itoa(micron_val, buf, 10); + + int text_len = strlen(buf); + int text_width = text_len * char_w + (text_len - 1); + int draw_x = cell_center_x - (text_width / 2); + + u8g.drawStr(draw_x, draw_y, buf); + } + } + } + } + else { + // GRAPHICAL VIEW: BALANCED BARYCENTRIC ADAPTIVE GRID + // EXPANDED AREA TO 56px: Fixes 7x7 mesh overlap from 2px down to exactly 1px maximum + const int grid_y_spacing = 56 / MESH_MAP_ROWS; + const int grid_x_spacing = grid_y_spacing; // Enforces a perfect square cell boundary + + const int total_grid_w = MESH_MAP_COLS * grid_x_spacing; + const int start_x = (100 - total_grid_w) / 2; + const int start_y = (64 - (MESH_MAP_ROWS * grid_y_spacing)) / 2; + + // FINAL SIMMETRICAL POSITIVE VECTOR MAP (48 ELEMENTS FOR 7x7 EXTREMUMS) + const int8_t path_pos_x[] = { 0, 1, 0, -1, 1, 1, -1, -1, 0, 2, 0, -2, 1, 2, 2, 1, -1, -2, -2, -1, 0, 2, 3, 2, 0, -2, -3, -2, 1, 3, 3, 1, -1, -3, -3, -1, 2, 3, 3, 2, -2, -3, -3, -2, 3, 3, -3, -3 }; + const int8_t path_pos_y[] = { -1, 0, 1, 0, -1, 1, 1, -1, -2, 0, 2, 0, -2, -1, 1, 2, 2, 1, -1, -2, -3, -2, 0, 2, 3, 2, 0, -2, -3, -1, 1, 3, 3, 1, -1, -3, -3, -1, 2, 3, 3, 2, -2, -3, -3, 3, 3, -3 }; + + // USER VALIDATED INVERTED SPECULAR NEGATIVE VECTOR MAP (48 ELEMENTS FOR 7x7 EXTREMUMS) + const int8_t path_neg_x[] = { -3, -3, 3, 3, -2, -3, -3, -2, 2, 3, 3, 2, -1, -3, -3, -1, 1, 3, 3, 1, -2, -3, -2, 0, 2, 3, 2, 0, -1, -2, -2, -1, 1, 2, 2, 1, -2, 0, 2, 0, -1, -1, 1, 1, -1, 0, 1, 0 }; + const int8_t path_neg_y[] = { -3, 3, 3, -3, -3, -2, 2, 3, 3, 2, -2, -3, -3, -1, 1, 3, 3, 1, -1, -3, -2, 0, 2, 3, 2, 0, -2, -3, -2, -1, 1, 2, 2, 1, -1, -2, 0, 2, 0, -2, -1, 1, 1, -1, 0, 1, 0, -1 }; + + for (uint8_t x = 0; x < MESH_MAP_COLS; x++) { + for (uint8_t y = 0; y < MESH_MAP_ROWS; y++) { + int16_t val = static_micron_values[x][y]; + + int center_x = start_x + (x * grid_x_spacing) + (grid_x_spacing / 2); + int center_y = start_y + ((MESH_MAP_ROWS - 1 - y) * grid_y_spacing) + (grid_y_spacing / 2); + + // Adaptive scaling calculations synchronized with firmware MESH_EDIT_Z_STEP + #ifdef MESH_EDIT_Z_STEP + const int16_t step_micron = (int16_t)(MESH_EDIT_Z_STEP * 1000.0); + #else + const int16_t step_micron = 25; + #endif + + int pixels_to_draw = (int)(abs(val) / (step_micron > 0 ? step_micron : 25)); + if (pixels_to_draw > 48) pixels_to_draw = 48; + + if (pixels_to_draw == 0) { + u8g.drawPixel(center_x, center_y); // Baseline unwarped flat reference pixel + } + else { + if (val > 0) { + // HIGH: Barycentric cluster grows outward using bright pixels + u8g.drawPixel(center_x, center_y); + for (int i = 0; i < pixels_to_draw; i++) { + u8g.drawPixel(center_x + path_pos_x[i], center_y + path_pos_y[i]); + } + } + else { + // LOW: 9x9 frame bounds an inward-collapsing specular matrix + u8g.drawFrame(center_x - 4, center_y - 4, 9, 9); + for (int i = 0; i < pixels_to_draw; i++) { + u8g.drawPixel(center_x + path_neg_x[i], center_y + path_neg_y[i]); + } + } + } + } + } + } + + // ACTION SIDEBAR NAVIGATION CONTROLS (X: 102-128) + u8g.setFont(u8g_font_6x10); + u8g.drawVLine(101, 0, 64); + + // BUTTON 1: VIS (Pixel Y: 2-15) + if (selected_button == 1) { + u8g.drawBox(103, 2, 23, 13); + u8g.setColorIndex(0); + u8g.drawStr(106, 12, "VIS"); + u8g.setColorIndex(1); + } else { + u8g.drawFrame(103, 2, 23, 13); + u8g.drawStr(106, 12, "VIS"); + } + + // BUTTON 2: INF (Pixel Y: 24-37) + if (selected_button == 2) { + u8g.drawBox(103, 24, 23, 13); + u8g.setColorIndex(0); + u8g.drawStr(106, 34, "INF"); + u8g.setColorIndex(1); + } else { + u8g.drawFrame(103, 24, 23, 13); + u8g.drawStr(106, 34, "INF"); + } + + // BUTTON 3: ESC (Pixel Y: 46-59) + if (selected_button == 3) { + u8g.drawBox(103, 46, 23, 13); + u8g.setColorIndex(0); + u8g.drawStr(106, 56, "ESC"); + u8g.setColorIndex(1); + } else { + u8g.drawFrame(103, 46, 23, 13); + u8g.drawStr(106, 56, "ESC"); + } +} + +#endif // HAS_MARLINUI_U8GLIB && ENABLED(BED_MESH_VIEWER) \ No newline at end of file From a51c6df4d2b4f1356a227a91425769c7a2f5dbc6 Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Wed, 29 Jul 2026 16:47:53 +0200 Subject: [PATCH 03/12] LCD: Integrate BED_MESH_VIEWER button into probe level menu Integrated the sub-menu activation button for the 2D mesh map visualizer inside menu_probe_level.cpp. The conditional call is placed right under the mesh edit option and is protected using native preprocessor guards to maintain cross-platform safety. --- Marlin/src/lcd/menu/menu_probe_level.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Marlin/src/lcd/menu/menu_probe_level.cpp b/Marlin/src/lcd/menu/menu_probe_level.cpp index db248c8d59f7..7c5578c0d2be 100644 --- a/Marlin/src/lcd/menu/menu_probe_level.cpp +++ b/Marlin/src/lcd/menu/menu_probe_level.cpp @@ -228,6 +228,10 @@ #endif // MESH_EDIT_MENU +#if ENABLED(BED_MESH_VIEWER) + extern void menu_bed_mesh_init(); +#endif + #if ENABLED(AUTO_BED_LEVELING_UBL) void _lcd_ubl_level_bed(); #endif @@ -295,6 +299,16 @@ void menu_probe_level() { if (is_valid) SUBMENU(MSG_EDIT_MESH, menu_edit_mesh); #endif + // + // >>> REAL-TIME PLATE MAP INSERTION IN MICRON <<< + // + #if ENABLED(BED_MESH_VIEWER) + if (is_valid) { + // The MENU_ITEM macro recognizes the LSTR object and applies the correct localization + MENU_ITEM(function, MSG_BED_MESH_VIEWER, menu_bed_mesh_init); + } + #endif + // // Mesh Bed Leveling Z-Offset // From 1fa58eca7a41db1e4f0b240fc25f509954838a99 Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Wed, 29 Jul 2026 16:50:16 +0200 Subject: [PATCH 04/12] Config: Enable BED_MESH_VIEWER testing parameters in configuration files Updated default Configuration.h and Configuration_adv.h with reference definitions to enable BED_MESH_VIEWER. Added structural macro anchors and specified MESH_EDIT_Z_STEP boundaries to provide a fully functional testbed for automated validation runners and simulators. --- Marlin/Configuration.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index f10451c3ba23..54ad06e33b30 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -2364,6 +2364,7 @@ #define MESH_EDIT_Z_STEP 0.025 // (mm) Step size while manually probing Z axis. #define LCD_PROBE_Z_RANGE 4 // (mm) Z Range centered on Z_MIN_POS for LCD Z adjustment //#define MESH_EDIT_MENU // Add a menu to edit mesh points + #define MESH_EDIT_MENU // Add a menu to edit mesh points #endif // Add a menu item to move between bed corners for manual bed adjustment From 84adaefa592383752319f655fd1a2f6ace2874d8 Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Wed, 29 Jul 2026 16:51:14 +0200 Subject: [PATCH 05/12] Localization: Add BED_MESH_VIEWER string definitions for EN and IT Registered the official `MSG_BED_MESH_VIEWER` localization labels using the native `LSTR` variable structure. Added explicit translations for both English and Italian dictionaries to ensure clean cross-compilation across core display modules. --- Marlin/src/lcd/language/language_en.h | 1 + Marlin/src/lcd/language/language_it.h | 1 + 2 files changed, 2 insertions(+) diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h index 4fe241678565..1804a4e5850e 100644 --- a/Marlin/src/lcd/language/language_en.h +++ b/Marlin/src/lcd/language/language_en.h @@ -279,6 +279,7 @@ namespace LanguageNarrow_en { LSTR MSG_NEXT_CORNER = _UxGT("Next Corner"); LSTR MSG_MESH_EDITOR = _UxGT("Mesh Editor"); LSTR MSG_EDIT_MESH = _UxGT("Edit Mesh"); + LSTR MSG_BED_MESH_VIEWER = _UxGT("Bed Mesh Map"); LSTR MSG_EDITING_STOPPED = _UxGT("Mesh Editing Stopped"); LSTR MSG_PROBING_POINT = _UxGT("Probing Point"); LSTR MSG_MESH_X = _UxGT("Index X"); diff --git a/Marlin/src/lcd/language/language_it.h b/Marlin/src/lcd/language/language_it.h index b559e7871a05..4493818d037c 100644 --- a/Marlin/src/lcd/language/language_it.h +++ b/Marlin/src/lcd/language/language_it.h @@ -257,6 +257,7 @@ namespace LanguageNarrow_it { LSTR MSG_NEXT_CORNER = _UxGT("Prossimo punto"); // Next Corner LSTR MSG_MESH_EDITOR = _UxGT("Editor mesh"); // Mesh Editor LSTR MSG_EDIT_MESH = _UxGT("Modifica mesh"); // Edit Mesh + LSTR MSG_BED_MESH_VIEWER = _UxGT("Mappa Piatto"); LSTR MSG_EDITING_STOPPED = _UxGT("Modif. mesh fermata"); // Mesh Editing Stopped LSTR MSG_PROBING_POINT = _UxGT("Punto sondato"); // Probing Point LSTR MSG_MESH_X = _UxGT("Indice X"); // Index X From f581aff67266ca4ab7d7fc00cd57e12acb53e871 Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Wed, 29 Jul 2026 18:54:44 +0200 Subject: [PATCH 06/12] correct typo --- Marlin/Configuration.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 54ad06e33b30..69d95212bac9 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -2364,7 +2364,7 @@ #define MESH_EDIT_Z_STEP 0.025 // (mm) Step size while manually probing Z axis. #define LCD_PROBE_Z_RANGE 4 // (mm) Z Range centered on Z_MIN_POS for LCD Z adjustment //#define MESH_EDIT_MENU // Add a menu to edit mesh points - #define MESH_EDIT_MENU // Add a menu to edit mesh points + #define BED_MESH_VIEWER // Activate the stable center graphic and numerical plate map #endif // Add a menu item to move between bed corners for manual bed adjustment From 16953f42ab7649b524fac36357b5373086cd3dcb Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Wed, 29 Jul 2026 19:08:27 +0200 Subject: [PATCH 07/12] better to leave it as default --- Marlin/Configuration.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 69d95212bac9..f6e350f0d9fc 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -2364,7 +2364,7 @@ #define MESH_EDIT_Z_STEP 0.025 // (mm) Step size while manually probing Z axis. #define LCD_PROBE_Z_RANGE 4 // (mm) Z Range centered on Z_MIN_POS for LCD Z adjustment //#define MESH_EDIT_MENU // Add a menu to edit mesh points - #define BED_MESH_VIEWER // Activate the stable center graphic and numerical plate map + //#define BED_MESH_VIEWER // Activate the stable center graphic and numerical plate map #endif // Add a menu item to move between bed corners for manual bed adjustment From da44ef24a4934bf77963ff34babb7feadc3b6a8e Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Wed, 29 Jul 2026 20:49:58 +0200 Subject: [PATCH 08/12] LCD: Upgrade bed mesh scale typography to u8g_font_6x12 with hex escape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upgraded the bottom scale legend inside menu_bed_mesh.cpp to use the official u8g_font_6x12 typeface for enhanced legibility. Replaced the manual pixel-by-pixel micro-drawing block of the 'µ' symbol with a clean string interpolation using the native '\xB5' hex escape sequence, preventing duplicate byte UTF-8 rendering artifacts. --- Marlin/src/lcd/dogm/menu_bed_mesh.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/Marlin/src/lcd/dogm/menu_bed_mesh.cpp b/Marlin/src/lcd/dogm/menu_bed_mesh.cpp index 470481007b48..bd2b19d0ab68 100644 --- a/Marlin/src/lcd/dogm/menu_bed_mesh.cpp +++ b/Marlin/src/lcd/dogm/menu_bed_mesh.cpp @@ -166,20 +166,17 @@ void menu_bed_mesh_draw() { const int16_t step_micron = 25; #endif - char step_buf[6]; - itoa(step_micron, step_buf, 10); - - u8g.setFont(u8g_font_5x7); - u8g.drawStr(6, 60, "1 Px ="); - u8g.drawStr(44, 60, step_buf); + // Buffer to store the formatted scale string + char step_buf[20]; + + // Fixed: Uses the strict hex escape \xB5 for the 'µ' symbol to prevent UTF-8 dual-byte encoding artifacts + sprintf_P(step_buf, PSTR("1 Px = %d \xB5m"), step_micron); - // Pixel-by-pixel micro-drawing of the micro symbol 'µm' due to lack of character map support on basic LCD fonts - int label_offset_x = 44 + (strlen(step_buf) * 6); - u8g.drawVLine(label_offset_x, 56, 4); // Left leg - u8g.drawVLine(label_offset_x + 2, 56, 4); // Right leg - u8g.drawHLine(label_offset_x, 59, 3); // Bottom join - u8g.drawPixel(label_offset_x - 1, 59); // Entry tick - u8g.drawStr(label_offset_x + 4, 60, "m"); // Appends final 'm' + // Switch to the official U8glib 6x12 font which includes full Latin-1 character map support + u8g.setFont(u8g_font_6x12); + + // Draw the unified scale string at a calibrated Y-axis baseline to prevent bottom bezel clipping + u8g.drawStr(6, 62, step_buf); // 4. INTERNATIONAL VERTICAL EXIT COMBINED ICON STRUCTURE (BOTTOM RIGHT) const int exit_x = 112; @@ -382,4 +379,4 @@ void menu_bed_mesh_draw() { } } -#endif // HAS_MARLINUI_U8GLIB && ENABLED(BED_MESH_VIEWER) \ No newline at end of file +#endif // HAS_MARLINUI_U8GLIB && ENABLED(BED_MESH_VIEWER) From 4a59ae96628edbdf8aadc95d5df3103500836166 Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Thu, 30 Jul 2026 09:19:34 +0200 Subject: [PATCH 09/12] LCD: Maximize formula scale legibility using u8g_font_7x14 as optimal compromise Upgraded the bottom mathematical scale display inside menu_bed_mesh.cpp to u8g_font_7x14 to maximize text size and character sharpness. This specific typeface was selected as the optimal engineering compromise: it provides the highest possible visual legibility on 12864 screens while guaranteeing a strict hardware clearance zone, preventing any potential lateral collision or overlapping with the adjacent exit icon. --- Marlin/src/lcd/dogm/menu_bed_mesh.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Marlin/src/lcd/dogm/menu_bed_mesh.cpp b/Marlin/src/lcd/dogm/menu_bed_mesh.cpp index bd2b19d0ab68..536cbf8f40f2 100644 --- a/Marlin/src/lcd/dogm/menu_bed_mesh.cpp +++ b/Marlin/src/lcd/dogm/menu_bed_mesh.cpp @@ -172,11 +172,11 @@ void menu_bed_mesh_draw() { // Fixed: Uses the strict hex escape \xB5 for the 'µ' symbol to prevent UTF-8 dual-byte encoding artifacts sprintf_P(step_buf, PSTR("1 Px = %d \xB5m"), step_micron); - // Switch to the official U8glib 6x12 font which includes full Latin-1 character map support - u8g.setFont(u8g_font_6x12); + // Switch to the official U8glib 7x14 font which includes full Latin-1 character map support + u8g.setFont(u8g_font_7x14); // Draw the unified scale string at a calibrated Y-axis baseline to prevent bottom bezel clipping - u8g.drawStr(6, 62, step_buf); + u8g.drawStr(6, 60, step_buf); // 4. INTERNATIONAL VERTICAL EXIT COMBINED ICON STRUCTURE (BOTTOM RIGHT) const int exit_x = 112; From fd27f58ce30f6891aec107a0bbaede6430caadda Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Sat, 1 Aug 2026 13:09:43 +0200 Subject: [PATCH 10/12] LCD: Upgrade bed mesh to 10x10 and redesign menus - Expanded menu_bed_mesh.cpp to dynamically support high-density layouts up to 10x10. - Maximize screen real estate by utilizing the full 64px display height for a more balanced grid. - Implemented full native support for asymmetric and rectangular mesh configurations without layout distortion. - Added a borderless sidebar that contracts to 10px in numeric view for 10+ columns, switching words to mono-letters and stacking ESC vertically. --- Marlin/src/lcd/dogm/menu_bed_mesh.cpp | 181 +++++++++++++++++--------- 1 file changed, 122 insertions(+), 59 deletions(-) diff --git a/Marlin/src/lcd/dogm/menu_bed_mesh.cpp b/Marlin/src/lcd/dogm/menu_bed_mesh.cpp index 536cbf8f40f2..56e2075baeac 100644 --- a/Marlin/src/lcd/dogm/menu_bed_mesh.cpp +++ b/Marlin/src/lcd/dogm/menu_bed_mesh.cpp @@ -8,10 +8,10 @@ // Official header to expose the 'bedlevel' (mesh_bed_leveling) class instance #include "../../feature/bedlevel/bedlevel.h" -#define MESH_MAP_COLS _MIN(GRID_MAX_POINTS_X, 7) -#define MESH_MAP_ROWS _MIN(GRID_MAX_POINTS_Y, 7) +#define MESH_MAP_COLS _MIN(GRID_MAX_POINTS_X, 10) +#define MESH_MAP_ROWS _MIN(GRID_MAX_POINTS_Y, 10) -static int16_t static_micron_values[7][7]; +static int16_t static_micron_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; static bool view_mode_numeric = false; static bool view_mode_help = false; // Flag to activate the full-screen exclusive Help Screen static uint8_t selected_button = 1; // 1 = VIS, 2 = INFO, 3 = ESC @@ -24,8 +24,8 @@ void menu_bed_mesh_init() { view_mode_numeric = false; view_mode_help = false; - for (uint8_t x = 0; x < 7; x++) { - for (uint8_t y = 0; y < 7; y++) { + for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++) { + for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++) { static_micron_values[x][y] = 0; } } @@ -221,25 +221,21 @@ void menu_bed_mesh_draw() { // ========================================================================= // MODAL NUMERIC VIEW WITH ADAPTIVE ANTI-OVERLAP BOUNDS (FULL WIDTH) // ========================================================================= - - // Uses full left screen width (100px) - grid spacing adjusts per column count - const int num_x_spacing = 100 / MESH_MAP_COLS; // Evaluates to 14px for 7x7/6x6, and 20px for 5x5 - const int num_y_spacing = 54 / MESH_MAP_ROWS; - - const int start_num_x = (100 - (MESH_MAP_COLS * num_x_spacing)) / 2; + const int max_w = (MESH_MAP_COLS > 9) ? 120 : 108; + const int num_x_spacing = max_w / MESH_MAP_COLS; + const int num_y_spacing = 64 / MESH_MAP_ROWS; + + const int start_num_x = (max_w - (MESH_MAP_COLS * num_x_spacing)) / 2; const int start_num_y = (64 - (MESH_MAP_ROWS * num_y_spacing)) / 2; - // Dynamic font assignment to prevent overlapping on high density meshes (6x6 and 7x7) - int char_w = 5; - int char_h = 7; - if (MESH_MAP_COLS > 5) { - u8g.setFont(u8g_font_4x6); // Ultra-compact 4px width font for 6x6 and 7x7 meshes - char_w = 4; - char_h = 6; + // Hardcoded bounding box widths for strict non-proportional evaluation + int char_w = 5, char_h = 7; + if (MESH_MAP_COLS > 7 || MESH_MAP_ROWS > 7) { + u8g.setFont(u8g_font_micro); char_w = 3; char_h = 5; + } else if (MESH_MAP_COLS > 5 || MESH_MAP_ROWS > 5) { + u8g.setFont(u8g_font_4x6); char_w = 4; char_h = 6; } else { - u8g.setFont(u8g_font_5x7); // Standard 5px width font for meshes up to 5x5 - char_w = 5; - char_h = 7; + u8g.setFont(u8g_font_5x7); char_w = 5; char_h = 7; } for (uint8_t x = 0; x < MESH_MAP_COLS; x++) { @@ -259,12 +255,25 @@ void menu_bed_mesh_draw() { micron_val = -micron_val; itoa(micron_val, buf, 10); + // Static math calculation with dynamic tracking and 1px subtraction int text_len = strlen(buf); - int text_width = text_len * char_w + (text_len - 1); + + // Extracts the condition to understand if we are in 8x8/9x9 (Tier 3) or lower + const bool is_dense = (MESH_MAP_COLS > 7 || MESH_MAP_ROWS > 7); + + int text_width = is_dense + ? ((text_len * char_w) + (text_len - 1)) - 1 + : u8g.getStrWidth(buf) - 1; + int draw_x = cell_center_x - (text_width / 2); - // Draws white bounding box tailored to the currently active font geometry - u8g.drawBox(draw_x - 1, draw_y - char_h, text_width + 2, char_h + 2); + // For dense meshes (Tier 3), we shift the box start 1px to the left (draw_x - 2) and 1px up (draw_y - char_h - 1) + // while expanding width (+3) and height (+2) to inject the missing 1px border on top and left. + if (is_dense) { + u8g.drawBox(draw_x - 1, draw_y - char_h - 1, text_width + 3, char_h + 2); + } else { + u8g.drawBox(draw_x - 1, draw_y - char_h, text_width + 2, char_h + 1); // Retains 7x7 perfection + } u8g.setColorIndex(0); u8g.drawStr(draw_x, draw_y, buf); @@ -274,23 +283,29 @@ void menu_bed_mesh_draw() { // --- POSITIVE VALUE (Standard bright text centered layout) --- itoa(micron_val, buf, 10); + // Static non-proportional grid width math calculation int text_len = strlen(buf); - int text_width = text_len * char_w + (text_len - 1); + int text_width = (text_len * char_w) + (text_len - 1); int draw_x = cell_center_x - (text_width / 2); u8g.drawStr(draw_x, draw_y, buf); } } } - } + } else { + // ========================================================================= // GRAPHICAL VIEW: BALANCED BARYCENTRIC ADAPTIVE GRID - // EXPANDED AREA TO 56px: Fixes 7x7 mesh overlap from 2px down to exactly 1px maximum - const int grid_y_spacing = 56 / MESH_MAP_ROWS; - const int grid_x_spacing = grid_y_spacing; // Enforces a perfect square cell boundary + // ========================================================================= + const int max_possible_x_space = 108 / MESH_MAP_COLS; + const int max_possible_y_space = 64 / MESH_MAP_ROWS; + + // Enforces a perfect square cell using the smallest available boundary as the master spacing + const int grid_y_spacing = (max_possible_x_space < max_possible_y_space) ? max_possible_x_space : max_possible_y_space; + const int grid_x_spacing = grid_y_spacing; const int total_grid_w = MESH_MAP_COLS * grid_x_spacing; - const int start_x = (100 - total_grid_w) / 2; + const int start_x = (108 - total_grid_w) / 2; const int start_y = (64 - (MESH_MAP_ROWS * grid_y_spacing)) / 2; // FINAL SIMMETRICAL POSITIVE VECTOR MAP (48 ELEMENTS FOR 7x7 EXTREMUMS) @@ -301,6 +316,27 @@ void menu_bed_mesh_draw() { const int8_t path_neg_x[] = { -3, -3, 3, 3, -2, -3, -3, -2, 2, 3, 3, 2, -1, -3, -3, -1, 1, 3, 3, 1, -2, -3, -2, 0, 2, 3, 2, 0, -1, -2, -2, -1, 1, 2, 2, 1, -2, 0, 2, 0, -1, -1, 1, 1, -1, 0, 1, 0 }; const int8_t path_neg_y[] = { -3, 3, 3, -3, -3, -2, 2, 3, 3, 2, -2, -3, -3, -1, 1, 3, 3, 1, -1, -3, -2, 0, 2, 3, 2, 0, -2, -3, -2, -1, 1, 2, 2, 1, -1, -2, 0, 2, 0, -2, -1, 1, 1, -1, 0, 1, 0, -1 }; + // >>> SPECIFIC SEQUENCES FOR 8x8 AND 9x9 DENSE MESHES <<< + const int8_t path_dense_pos_x[] = { 0, 1, 0, -1, 1, 1, -1, -1, 0, 2, 0, -2, 1, 2, 2, 1, -1, -2, -2, -1, 2, 2, -2, -2}; + const int8_t path_dense_pos_y[] = { -1, 0, 1, 0, -1, 1, 1, -1, -2, 0, 2, 0, -2, -1, 1, 2, 2, 1, -1, -2, -2, 2, 2, -2}; + + const int8_t path_dense_neg_x[] = { -2, -2, 2, 2, -1, -2, -2, -1, 1, 2, 2, 1, -2, 0, 2, 0, -1, -1, 1, 1, -1, 0, 1, 0 }; + const int8_t path_dense_neg_y[] = { -2, 2, 2, -2, -2, -1, 1, 2, 2, 1, -1, -2, 0, 2, 0, -2, -1, 1, 1, -1, 0, 1, 0, -1 }; + + // Multi-tier structural clearance heuristic based on critical threshold boundaries + const int8_t *current_pos_x = path_pos_x, *current_pos_y = path_pos_y; + const int8_t *current_neg_x = path_neg_x, *current_neg_y = path_neg_y; + int max_allowed_pixels = 48, frame_offset = 4, frame_size = 9; + + // Trigger Tier 2 if rows exceed 7 OR if columns exceed the 11-point horizontal threshold + if (MESH_MAP_ROWS > 7 || MESH_MAP_COLS > 11) { + current_pos_x = path_dense_pos_x; current_pos_y = path_dense_pos_y; + current_neg_x = path_dense_neg_x; current_neg_y = path_dense_neg_y; + max_allowed_pixels = 24; + frame_offset = 3; + frame_size = 7; // Forces the safer, tight 7x7 frame layout + } + for (uint8_t x = 0; x < MESH_MAP_COLS; x++) { for (uint8_t y = 0; y < MESH_MAP_ROWS; y++) { int16_t val = static_micron_values[x][y]; @@ -316,7 +352,9 @@ void menu_bed_mesh_draw() { #endif int pixels_to_draw = (int)(abs(val) / (step_micron > 0 ? step_micron : 25)); - if (pixels_to_draw > 48) pixels_to_draw = 48; + + // FIXED: Clamped using the dynamic variable to prevent out-of-bounds memory read + if (pixels_to_draw > max_allowed_pixels) pixels_to_draw = max_allowed_pixels; if (pixels_to_draw == 0) { u8g.drawPixel(center_x, center_y); // Baseline unwarped flat reference pixel @@ -326,14 +364,17 @@ void menu_bed_mesh_draw() { // HIGH: Barycentric cluster grows outward using bright pixels u8g.drawPixel(center_x, center_y); for (int i = 0; i < pixels_to_draw; i++) { - u8g.drawPixel(center_x + path_pos_x[i], center_y + path_pos_y[i]); + // FIXED: Uses active pointer tracking instead of hardcoded 7x7 maps + u8g.drawPixel(center_x + current_pos_x[i], center_y + current_pos_y[i]); } } else { - // LOW: 9x9 frame bounds an inward-collapsing specular matrix - u8g.drawFrame(center_x - 4, center_y - 4, 9, 9); + // LOW: FIXED - Draws frame using dynamic pre-calculated sizing parameters + u8g.drawFrame(center_x - frame_offset, center_y - frame_offset, frame_size, frame_size); + for (int i = 0; i < pixels_to_draw; i++) { - u8g.drawPixel(center_x + path_neg_x[i], center_y + path_neg_y[i]); + // FIXED: Uses active pointer tracking instead of hardcoded 7x7 maps + u8g.drawPixel(center_x + current_neg_x[i], center_y + current_neg_y[i]); } } } @@ -341,42 +382,64 @@ void menu_bed_mesh_draw() { } } - // ACTION SIDEBAR NAVIGATION CONTROLS (X: 102-128) + // ACTION SIDEBAR NAVIGATION CONTROLS (X: 109-128) u8g.setFont(u8g_font_6x10); - u8g.drawVLine(101, 0, 64); - // BUTTON 1: VIS (Pixel Y: 2-15) + // Dynamic sidebar boundary assignment: 120px for ultra-dense meshes, 110px for standard ones + const bool is_ultra_dense = (view_mode_numeric && MESH_MAP_COLS > 9); + const int btn_x = is_ultra_dense ? 121 : 109; + const int btn_w = is_ultra_dense ? 10 : 21; + + // FIXED: Dynamic vertical spacing to achieve absolute equidistance in both configurations + const int inf_y = is_ultra_dense ? 19 : 21; + const int esc_y = is_ultra_dense ? 37 : 41; + const int esc_h = is_ultra_dense ? 27 : 13; // Handwired 27px tall box to fit 7px uppercase letters perfectly + + // --- BUTTON 1: VIS / V --- if (selected_button == 1) { - u8g.drawBox(103, 2, 23, 13); - u8g.setColorIndex(0); - u8g.drawStr(106, 12, "VIS"); - u8g.setColorIndex(1); + u8g.drawBox(btn_x, 1, btn_w, 13); + u8g.setColorIndex(0); + u8g.drawStr(btn_x + 2, 11, is_ultra_dense ? "V" : "VIS"); + u8g.setColorIndex(1); } else { - u8g.drawFrame(103, 2, 23, 13); - u8g.drawStr(106, 12, "VIS"); + u8g.drawFrame(btn_x, 1, btn_w, 13); + u8g.drawStr(btn_x + 2, 11, is_ultra_dense ? "V" : "VIS"); } - // BUTTON 2: INF (Pixel Y: 24-37) + // --- BUTTON 2: INF / I --- if (selected_button == 2) { - u8g.drawBox(103, 24, 23, 13); - u8g.setColorIndex(0); - u8g.drawStr(106, 34, "INF"); - u8g.setColorIndex(1); + u8g.drawBox(btn_x, inf_y, btn_w, 13); + u8g.setColorIndex(0); + u8g.drawStr(btn_x + 2, inf_y + 10, is_ultra_dense ? "I" : "INF"); + u8g.setColorIndex(1); } else { - u8g.drawFrame(103, 24, 23, 13); - u8g.drawStr(106, 34, "INF"); + u8g.drawFrame(btn_x, inf_y, btn_w, 13); + u8g.drawStr(btn_x + 2, inf_y + 10, is_ultra_dense ? "I" : "INF"); } - // BUTTON 3: ESC (Pixel Y: 46-59) + // --- BUTTON 3: ESC / VERTICAL ESC --- if (selected_button == 3) { - u8g.drawBox(103, 46, 23, 13); - u8g.setColorIndex(0); - u8g.drawStr(106, 56, "ESC"); - u8g.setColorIndex(1); + u8g.drawBox(btn_x, esc_y, btn_w, esc_h); + u8g.setColorIndex(0); + if (is_ultra_dense) { + // FIXED: Perfectly balanced 1px margins with 7px tall characters over 27px box bounds + u8g.drawStr(btn_x + 2, esc_y + 9, "E"); // Top letter (baseline at +8) + u8g.drawStr(btn_x + 2, esc_y + 17, "S"); // Middle letter (baseline at +16) + u8g.drawStr(btn_x + 2, esc_y + 25, "C"); // Bottom letter (baseline at +24) + } else { + u8g.drawStr(btn_x + 2, esc_y + 10, "ESC"); + } + u8g.setColorIndex(1); } else { - u8g.drawFrame(103, 46, 23, 13); - u8g.drawStr(106, 56, "ESC"); + u8g.drawFrame(btn_x, esc_y, btn_w, esc_h); + if (is_ultra_dense) { + u8g.drawStr(btn_x + 2, esc_y + 9, "E"); + u8g.drawStr(btn_x + 2, esc_y + 17, "S"); + u8g.drawStr(btn_x + 2, esc_y + 25, "C"); + } else { + u8g.drawStr(btn_x + 2, esc_y + 10, "ESC"); + } } } -#endif // HAS_MARLINUI_U8GLIB && ENABLED(BED_MESH_VIEWER) +#endif // HAS_MARLINUI_U8GLIB && ENABLED(BED_MESH_VIEWER) \ No newline at end of file From c7d4dae72e1e9898d322cbb3059b12ce9f0b33a6 Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Sun, 2 Aug 2026 09:44:04 +0200 Subject: [PATCH 11/12] Fix potential buffer truncation warning in menu_probe_level.cpp Increase MString buffer size from 10 to 12 in _lcd_level_bed_moving() to prevent compiler warnings about potential format truncation when displaying manual probe points. --- Marlin/src/lcd/menu/menu_probe_level.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/lcd/menu/menu_probe_level.cpp b/Marlin/src/lcd/menu/menu_probe_level.cpp index 7c5578c0d2be..1b51f93791d5 100644 --- a/Marlin/src/lcd/menu/menu_probe_level.cpp +++ b/Marlin/src/lcd/menu/menu_probe_level.cpp @@ -144,7 +144,7 @@ // void _lcd_level_bed_moving() { if (ui.should_draw()) { - MString<10> msg; + MString<12> msg; msg.setf(F(" %i / %u"), int(manual_probe_index + 1), total_probe_points); MenuItem_static::draw(LCD_HEIGHT / 2, GET_TEXT_F(MSG_LEVEL_BED_NEXT_POINT), SS_CENTER, msg); } From a8c9ea0244e07f81b1049fb77384e6a9edd6751e Mon Sep 17 00:00:00 2001 From: fanXbox <107966612+fanXbox@users.noreply.github.com> Date: Sun, 2 Aug 2026 09:49:31 +0200 Subject: [PATCH 12/12] Fix Italian translation for bed leveling UI - Shorten the Italian translation for bed leveling messages to prevent text from overflowing the LCD screen. --- Marlin/src/lcd/language/language_it.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/src/lcd/language/language_it.h b/Marlin/src/lcd/language/language_it.h index 4493818d037c..3cafa7c4d444 100644 --- a/Marlin/src/lcd/language/language_it.h +++ b/Marlin/src/lcd/language/language_it.h @@ -65,7 +65,7 @@ namespace LanguageNarrow_it { LSTR MSG_AUTO_HOME_Z = _UxGT("Azzera Z"); // Home Z LSTR MSG_LEVEL_BED_HOMING = _UxGT("Home assi XYZ"); // Homing XYZ LSTR MSG_LEVEL_BED_WAITING = _UxGT("Premi per iniziare"); // Click to Begin - LSTR MSG_LEVEL_BED_NEXT_POINT = _UxGT("Punto successivo"); // Next Point + LSTR MSG_LEVEL_BED_NEXT_POINT = _UxGT("Rileva punto"); // Next Point LSTR MSG_LEVEL_BED_DONE = _UxGT("Livel. terminato!"); // Leveling Done! LSTR MSG_SET_HOME_OFFSETS = _UxGT("Imp. offset home"); // Set Home Offsets LSTR MSG_HOME_OFFSETS_APPLIED = _UxGT("Offset applicato"); // Offsets Applied