Streamline menu item logic (#17664)
This commit is contained in:
		@@ -319,7 +319,33 @@ class MenuItem_bool : public MenuEditItemBase {
 | 
			
		||||
////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SCREEN_OR_MENU_LOOP generates init code for a screen or menu
 | 
			
		||||
 * Marlin's native menu screens work by running a loop from the top visible line index
 | 
			
		||||
 * to the bottom visible line index (according to how much the screen has been scrolled).
 | 
			
		||||
 * This complete loop is done on every menu screen call.
 | 
			
		||||
 *
 | 
			
		||||
 * The menu system is highly dynamic, so it doesn't know ahead of any menu loop which
 | 
			
		||||
 * items will be visible or hidden, so menu items don't have a fixed index number.
 | 
			
		||||
 *
 | 
			
		||||
 * During the loop, each menu item checks to see if its line is the current one. If it is,
 | 
			
		||||
 * then it checks to see if a click has arrived so it can run its action. If the action
 | 
			
		||||
 * doesn't redirect to another screen then the menu item calls its draw method.
 | 
			
		||||
 *
 | 
			
		||||
 * Menu item add-ons can do whatever they like.
 | 
			
		||||
 *
 | 
			
		||||
 * This mixture of drawing and processing inside a loop has the advantage that a single
 | 
			
		||||
 * line can be used to represent a menu item, and that is the rationale for this design.
 | 
			
		||||
 *
 | 
			
		||||
 * One of the pitfalls of this method is that DOGM displays call the screen handler 2x,
 | 
			
		||||
 * 4x, or 8x per screen update to draw just one segment of the screen. As a result, any
 | 
			
		||||
 * menu item that exists in two screen segments is drawn and processed twice per screen
 | 
			
		||||
 * update. With each item processed 5, 10, 20, or 40 times the logic has to be simple.
 | 
			
		||||
 *
 | 
			
		||||
 * To keep performance optimal, use the MENU_ITEM_IF/ELSE/ELIF macros. If function calls
 | 
			
		||||
 * are needed to test conditions, they should come before START_MENU / START_SCREEN.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SCREEN_OR_MENU_LOOP generates header code for a screen or menu
 | 
			
		||||
 *
 | 
			
		||||
 *   encoderTopLine is the top menu line to display
 | 
			
		||||
 *   _lcdLineNr is the index of the LCD line (e.g., 0-3)
 | 
			
		||||
@@ -510,6 +536,17 @@ class MenuItem_bool : public MenuEditItemBase {
 | 
			
		||||
#define YESNO_ITEM_N_P(N,PLABEL, V...)      _CONFIRM_ITEM_N_P(N, PLABEL, ##V)
 | 
			
		||||
#define YESNO_ITEM_N(N,LABEL, V...)            YESNO_ITEM_N_P(N, GET_TEXT(LABEL), ##V)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MENU_ITEM_IF/ELSE/ELIF
 | 
			
		||||
 *
 | 
			
		||||
 * Apply a condition for a menu item to exist.
 | 
			
		||||
 * When the condition passes, NEXT_ITEM updates _thisItemNr.
 | 
			
		||||
 * This cannot be used to wrap multiple menu items.
 | 
			
		||||
 */
 | 
			
		||||
#define MENU_ITEM_IF(COND)        if ((_menuLineNr == _thisItemNr) && (COND))
 | 
			
		||||
#define MENU_ITEM_ELIF(COND) else if ((_menuLineNr == _thisItemNr) && (COND))
 | 
			
		||||
#define MENU_ITEM_ELSE       else if  (_menuLineNr == _thisItemNr)
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////
 | 
			
		||||
/////////////// Menu Screens ///////////////
 | 
			
		||||
////////////////////////////////////////////
 | 
			
		||||
 
 | 
			
		||||
@@ -45,7 +45,6 @@
 | 
			
		||||
 | 
			
		||||
#if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM
 | 
			
		||||
  #include "../../feature/runout.h"
 | 
			
		||||
  float lcd_runout_distance_mm;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ENABLED(EEPROM_SETTINGS) && DISABLED(SLIM_LCD_MENUS)
 | 
			
		||||
@@ -148,9 +147,12 @@ void menu_cancelobject();
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM
 | 
			
		||||
      EDIT_ITEM(float3, MSG_RUNOUT_DISTANCE_MM, &lcd_runout_distance_mm, 1, 30, []{
 | 
			
		||||
        runout.set_runout_distance(lcd_runout_distance_mm);
 | 
			
		||||
      });
 | 
			
		||||
      MENU_ITEM_IF(1) {
 | 
			
		||||
        editable.decimal = runout.runout_distance();
 | 
			
		||||
        EDIT_ITEM(float3, MSG_RUNOUT_DISTANCE_MM, &editable.decimal, 1, 30,
 | 
			
		||||
          []{ runout.set_runout_distance(editable.decimal); }, true
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    END_MENU();
 | 
			
		||||
@@ -327,9 +329,6 @@ void menu_cancelobject();
 | 
			
		||||
 | 
			
		||||
  // M203 / M205 Velocity options
 | 
			
		||||
  void menu_advanced_velocity() {
 | 
			
		||||
    START_MENU();
 | 
			
		||||
    BACK_ITEM(MSG_ADVANCED_SETTINGS);
 | 
			
		||||
 | 
			
		||||
    // M203 Max Feedrate
 | 
			
		||||
    constexpr xyze_feedrate_t max_fr_edit =
 | 
			
		||||
      #ifdef MAX_FEEDRATE_EDIT_VALUES
 | 
			
		||||
@@ -345,6 +344,10 @@ void menu_cancelobject();
 | 
			
		||||
    #else
 | 
			
		||||
      const xyze_feedrate_t &max_fr_edit_scaled = max_fr_edit;
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    START_MENU();
 | 
			
		||||
    BACK_ITEM(MSG_ADVANCED_SETTINGS);
 | 
			
		||||
 | 
			
		||||
    #define EDIT_VMAX(N) EDIT_ITEM_FAST(float3, MSG_VMAX_##N, &planner.settings.max_feedrate_mm_s[_AXIS(N)], 1, max_fr_edit_scaled[_AXIS(N)])
 | 
			
		||||
    EDIT_VMAX(A);
 | 
			
		||||
    EDIT_VMAX(B);
 | 
			
		||||
@@ -369,18 +372,7 @@ void menu_cancelobject();
 | 
			
		||||
 | 
			
		||||
  // M201 / M204 Accelerations
 | 
			
		||||
  void menu_advanced_acceleration() {
 | 
			
		||||
    START_MENU();
 | 
			
		||||
    BACK_ITEM(MSG_ADVANCED_SETTINGS);
 | 
			
		||||
 | 
			
		||||
    const float max_accel = _MAX(planner.settings.max_acceleration_mm_per_s2[A_AXIS], planner.settings.max_acceleration_mm_per_s2[B_AXIS], planner.settings.max_acceleration_mm_per_s2[C_AXIS]);
 | 
			
		||||
    // M204 P Acceleration
 | 
			
		||||
    EDIT_ITEM_FAST(float5_25, MSG_ACC, &planner.settings.acceleration, 25, max_accel);
 | 
			
		||||
 | 
			
		||||
    // M204 R Retract Acceleration
 | 
			
		||||
    EDIT_ITEM_FAST(float5, MSG_A_RETRACT, &planner.settings.retract_acceleration, 100, planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)]);
 | 
			
		||||
 | 
			
		||||
    // M204 T Travel Acceleration
 | 
			
		||||
    EDIT_ITEM_FAST(float5_25, MSG_A_TRAVEL, &planner.settings.travel_acceleration, 25, max_accel);
 | 
			
		||||
 | 
			
		||||
    // M201 settings
 | 
			
		||||
    constexpr xyze_ulong_t max_accel_edit =
 | 
			
		||||
@@ -398,6 +390,18 @@ void menu_cancelobject();
 | 
			
		||||
      const xyze_ulong_t &max_accel_edit_scaled = max_accel_edit;
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    START_MENU();
 | 
			
		||||
    BACK_ITEM(MSG_ADVANCED_SETTINGS);
 | 
			
		||||
 | 
			
		||||
    // M204 P Acceleration
 | 
			
		||||
    EDIT_ITEM_FAST(float5_25, MSG_ACC, &planner.settings.acceleration, 25, max_accel);
 | 
			
		||||
 | 
			
		||||
    // M204 R Retract Acceleration
 | 
			
		||||
    EDIT_ITEM_FAST(float5, MSG_A_RETRACT, &planner.settings.retract_acceleration, 100, planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)]);
 | 
			
		||||
 | 
			
		||||
    // M204 T Travel Acceleration
 | 
			
		||||
    EDIT_ITEM_FAST(float5_25, MSG_A_TRAVEL, &planner.settings.travel_acceleration, 25, max_accel);
 | 
			
		||||
 | 
			
		||||
    #define EDIT_AMAX(Q,L) EDIT_ITEM_FAST(long5_25, MSG_AMAX_##Q, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.reset_acceleration_rates(); })
 | 
			
		||||
    EDIT_AMAX(A, 100);
 | 
			
		||||
    EDIT_AMAX(B, 100);
 | 
			
		||||
@@ -413,8 +417,10 @@ void menu_cancelobject();
 | 
			
		||||
 | 
			
		||||
    #ifdef XY_FREQUENCY_LIMIT
 | 
			
		||||
      EDIT_ITEM(int8, MSG_XY_FREQUENCY_LIMIT, &planner.xy_freq_limit_hz, 0, 100, planner.refresh_frequency_limit, true);
 | 
			
		||||
      editable.uint8 = uint8_t(LROUND(planner.xy_freq_min_speed_factor * 255 * 100)); // percent to u8
 | 
			
		||||
      EDIT_ITEM(percent, MSG_XY_FREQUENCY_FEEDRATE, &editable.uint8, 3, 255, []{ planner.set_min_speed_factor_u8(editable.uint8); }, true);
 | 
			
		||||
      MENU_ITEM_IF(1) {
 | 
			
		||||
        editable.uint8 = uint8_t(LROUND(planner.xy_freq_min_speed_factor * 255 * 100)); // percent to u8
 | 
			
		||||
        EDIT_ITEM(percent, MSG_XY_FREQUENCY_FEEDRATE, &editable.uint8, 3, 255, []{ planner.set_min_speed_factor_u8(editable.uint8); }, true);
 | 
			
		||||
      }
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    END_MENU();
 | 
			
		||||
@@ -496,9 +502,8 @@ void menu_advanced_steps_per_mm() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void menu_advanced_settings() {
 | 
			
		||||
  #if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM
 | 
			
		||||
    lcd_runout_distance_mm = runout.runout_distance();
 | 
			
		||||
  #endif
 | 
			
		||||
  const bool is_busy = printer_busy();
 | 
			
		||||
 | 
			
		||||
  START_MENU();
 | 
			
		||||
  BACK_ITEM(MSG_CONFIGURATION);
 | 
			
		||||
 | 
			
		||||
@@ -522,13 +527,13 @@ void menu_advanced_settings() {
 | 
			
		||||
 | 
			
		||||
    // M851 - Z Probe Offsets
 | 
			
		||||
    #if HAS_BED_PROBE
 | 
			
		||||
      if (!printer_busy())
 | 
			
		||||
        SUBMENU(MSG_ZPROBE_OFFSETS, menu_probe_offsets);
 | 
			
		||||
      if (!is_busy) SUBMENU(MSG_ZPROBE_OFFSETS, menu_probe_offsets);
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
  #endif // !SLIM_LCD_MENUS
 | 
			
		||||
 | 
			
		||||
  // M92 - Steps Per mm
 | 
			
		||||
  if (!printer_busy())
 | 
			
		||||
  if (!is_busy)
 | 
			
		||||
    SUBMENU(MSG_STEPS_PER_MM, menu_advanced_steps_per_mm);
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(BACKLASH_GCODE)
 | 
			
		||||
@@ -571,17 +576,19 @@ void menu_advanced_settings() {
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(SD_FIRMWARE_UPDATE)
 | 
			
		||||
    bool sd_update_state = settings.sd_update_status();
 | 
			
		||||
    EDIT_ITEM(bool, MSG_MEDIA_UPDATE, &sd_update_state, []{
 | 
			
		||||
      //
 | 
			
		||||
      // Toggle the SD Firmware Update state in EEPROM
 | 
			
		||||
      //
 | 
			
		||||
      const bool new_state = !settings.sd_update_status(),
 | 
			
		||||
                 didset = settings.set_sd_update_status(new_state);
 | 
			
		||||
      TERN_(HAS_BUZZER, ui.completion_feedback(didset));
 | 
			
		||||
      ui.return_to_status();
 | 
			
		||||
      if (new_state) LCD_MESSAGEPGM(MSG_RESET_PRINTER); else ui.reset_status();
 | 
			
		||||
    });
 | 
			
		||||
    MENU_ITEM_IF (1) {
 | 
			
		||||
      bool sd_update_state = settings.sd_update_status();
 | 
			
		||||
      EDIT_ITEM(bool, MSG_MEDIA_UPDATE, &sd_update_state, []{
 | 
			
		||||
        //
 | 
			
		||||
        // Toggle the SD Firmware Update state in EEPROM
 | 
			
		||||
        //
 | 
			
		||||
        const bool new_state = !settings.sd_update_status(),
 | 
			
		||||
                   didset = settings.set_sd_update_status(new_state);
 | 
			
		||||
        ui.completion_feedback(didset);
 | 
			
		||||
        ui.return_to_status();
 | 
			
		||||
        if (new_state) LCD_MESSAGEPGM(MSG_RESET_PRINTER); else ui.reset_status();
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(EEPROM_SETTINGS) && DISABLED(SLIM_LCD_MENUS)
 | 
			
		||||
 
 | 
			
		||||
@@ -79,19 +79,14 @@ static inline void _lcd_level_bed_corners_homing() {
 | 
			
		||||
    bed_corner = 0;
 | 
			
		||||
    ui.goto_screen([]{
 | 
			
		||||
      MenuItem_confirm::select_screen(
 | 
			
		||||
        GET_TEXT(MSG_BUTTON_NEXT), GET_TEXT(MSG_BUTTON_DONE),
 | 
			
		||||
        _lcd_goto_next_corner,
 | 
			
		||||
        []{
 | 
			
		||||
          TERN_(HAS_LEVELING, set_bed_leveling_enabled(leveling_was_active));
 | 
			
		||||
          ui.goto_previous_screen_no_defer();
 | 
			
		||||
        },
 | 
			
		||||
        GET_TEXT(
 | 
			
		||||
          #if ENABLED(LEVEL_CENTER_TOO)
 | 
			
		||||
            MSG_LEVEL_BED_NEXT_POINT
 | 
			
		||||
          #else
 | 
			
		||||
            MSG_NEXT_CORNER
 | 
			
		||||
          #endif
 | 
			
		||||
        ), (PGM_P)nullptr, PSTR("?")
 | 
			
		||||
          GET_TEXT(MSG_BUTTON_NEXT), GET_TEXT(MSG_BUTTON_DONE)
 | 
			
		||||
        , _lcd_goto_next_corner
 | 
			
		||||
        , []{
 | 
			
		||||
            TERN_(HAS_LEVELING, set_bed_leveling_enabled(leveling_was_active));
 | 
			
		||||
            ui.goto_previous_screen_no_defer();
 | 
			
		||||
          }
 | 
			
		||||
        , GET_TEXT(TERN(LEVEL_CENTER_TOO, MSG_LEVEL_BED_NEXT_POINT, MSG_NEXT_CORNER))
 | 
			
		||||
        , (PGM_P)nullptr, PSTR("?")
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
    ui.set_selection(true);
 | 
			
		||||
 
 | 
			
		||||
@@ -224,11 +224,12 @@
 | 
			
		||||
 *    Save Settings       (Req: EEPROM_SETTINGS)
 | 
			
		||||
 */
 | 
			
		||||
void menu_bed_leveling() {
 | 
			
		||||
  const bool is_homed = all_axes_known(),
 | 
			
		||||
             is_valid = leveling_is_valid();
 | 
			
		||||
 | 
			
		||||
  START_MENU();
 | 
			
		||||
  BACK_ITEM(MSG_MOTION);
 | 
			
		||||
 | 
			
		||||
  const bool is_homed = all_axes_known();
 | 
			
		||||
 | 
			
		||||
  // Auto Home if not using manual probing
 | 
			
		||||
  #if NONE(PROBE_MANUALLY, MESH_BED_LEVELING)
 | 
			
		||||
    if (!is_homed) GCODES_ITEM(MSG_AUTO_HOME, G28_STR);
 | 
			
		||||
@@ -244,21 +245,22 @@ void menu_bed_leveling() {
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(MESH_EDIT_MENU)
 | 
			
		||||
    if (leveling_is_valid())
 | 
			
		||||
      SUBMENU(MSG_EDIT_MESH, menu_edit_mesh);
 | 
			
		||||
    if (is_valid) SUBMENU(MSG_EDIT_MESH, menu_edit_mesh);
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  // Homed and leveling is valid? Then leveling can be toggled.
 | 
			
		||||
  if (is_homed && leveling_is_valid()) {
 | 
			
		||||
  if (is_homed && is_valid) {
 | 
			
		||||
    bool show_state = planner.leveling_active;
 | 
			
		||||
    EDIT_ITEM(bool, MSG_BED_LEVELING, &show_state, _lcd_toggle_bed_leveling);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Z Fade Height
 | 
			
		||||
  #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
 | 
			
		||||
    // Shadow for editing the fade height
 | 
			
		||||
    editable.decimal = planner.z_fade_height;
 | 
			
		||||
    EDIT_ITEM_FAST(float3, MSG_Z_FADE_HEIGHT, &editable.decimal, 0, 100, []{ set_z_fade_height(editable.decimal); });
 | 
			
		||||
    MENU_ITEM_IF (1) {
 | 
			
		||||
      // Shadow for editing the fade height
 | 
			
		||||
      editable.decimal = planner.z_fade_height;
 | 
			
		||||
      EDIT_ITEM_FAST(float3, MSG_Z_FADE_HEIGHT, &editable.decimal, 0, 100, []{ set_z_fade_height(editable.decimal); });
 | 
			
		||||
    }
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
 
 | 
			
		||||
@@ -53,17 +53,19 @@ static void lcd_cancel_object_confirm() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void menu_cancelobject() {
 | 
			
		||||
  const int8_t ao = cancelable.active_object;
 | 
			
		||||
 | 
			
		||||
  START_MENU();
 | 
			
		||||
  BACK_ITEM(MSG_MAIN);
 | 
			
		||||
 | 
			
		||||
  // Draw cancelable items in a loop
 | 
			
		||||
  int8_t a = cancelable.active_object;
 | 
			
		||||
  for (int8_t i = -1; i < cancelable.object_count; i++) {
 | 
			
		||||
    if (i == a) continue;
 | 
			
		||||
    int8_t j = i < 0 ? a : i;
 | 
			
		||||
    if (!cancelable.is_canceled(j))
 | 
			
		||||
      SUBMENU_N(j, MSG_CANCEL_OBJECT_N, lcd_cancel_object_confirm);
 | 
			
		||||
    if (i < 0) SKIP_ITEM();
 | 
			
		||||
    if (i == ao) continue;                                          // Active is drawn on -1 index
 | 
			
		||||
    const int8_t j = i < 0 ? ao : i;                                // Active or index item
 | 
			
		||||
    MENU_ITEM_IF (!cancelable.is_canceled(j)) {                     // Not canceled already?
 | 
			
		||||
      SUBMENU_N(j, MSG_CANCEL_OBJECT_N, lcd_cancel_object_confirm); // Offer the option.
 | 
			
		||||
      if (i < 0) SKIP_ITEM();                                       // Extra line after active
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  END_MENU();
 | 
			
		||||
 
 | 
			
		||||
@@ -126,6 +126,8 @@ void menu_advanced_settings();
 | 
			
		||||
    #include "../../module/motion.h" // for active_extruder
 | 
			
		||||
 | 
			
		||||
    void menu_toolchange_migration() {
 | 
			
		||||
      PGM_P const msg_migrate = GET_TEXT(MSG_TOOL_MIGRATION_SWAP);
 | 
			
		||||
 | 
			
		||||
      START_MENU();
 | 
			
		||||
      BACK_ITEM(MSG_CONFIGURATION);
 | 
			
		||||
 | 
			
		||||
@@ -134,7 +136,6 @@ void menu_advanced_settings();
 | 
			
		||||
      EDIT_ITEM(uint8, MSG_TOOL_MIGRATION_END, &migration.last, 0, EXTRUDERS - 1);
 | 
			
		||||
 | 
			
		||||
      // Migrate to a chosen extruder
 | 
			
		||||
      PGM_P const msg_migrate = GET_TEXT(MSG_TOOL_MIGRATION_SWAP);
 | 
			
		||||
      LOOP_L_N(s, EXTRUDERS) {
 | 
			
		||||
        if (s != active_extruder) {
 | 
			
		||||
          ACTION_ITEM_N_P(s, msg_migrate, []{
 | 
			
		||||
@@ -182,11 +183,12 @@ void menu_advanced_settings();
 | 
			
		||||
#if ENABLED(DUAL_X_CARRIAGE)
 | 
			
		||||
 | 
			
		||||
  void menu_idex() {
 | 
			
		||||
    const bool need_g28 = !(TEST(axis_known_position, Y_AXIS) && TEST(axis_known_position, Z_AXIS));
 | 
			
		||||
 | 
			
		||||
    START_MENU();
 | 
			
		||||
    BACK_ITEM(MSG_CONFIGURATION);
 | 
			
		||||
 | 
			
		||||
    GCODES_ITEM(MSG_IDEX_MODE_AUTOPARK,  PSTR("M605 S1\nG28 X\nG1 X100"));
 | 
			
		||||
    const bool need_g28 = !(TEST(axis_known_position, Y_AXIS) && TEST(axis_known_position, Z_AXIS));
 | 
			
		||||
    GCODES_ITEM(MSG_IDEX_MODE_DUPLICATE, need_g28
 | 
			
		||||
      ? PSTR("M605 S1\nT0\nG28\nM605 S2 X200\nG28 X\nG1 X100")                // If Y or Z is not homed, do a full G28 first
 | 
			
		||||
      : PSTR("M605 S1\nT0\nM605 S2 X200\nG28 X\nG1 X100")
 | 
			
		||||
@@ -237,9 +239,10 @@ void menu_advanced_settings();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ENABLED(TOUCH_MI_PROBE)
 | 
			
		||||
 | 
			
		||||
  void menu_touchmi() {
 | 
			
		||||
    START_MENU();
 | 
			
		||||
    ui.defer_status_screen();
 | 
			
		||||
    START_MENU();
 | 
			
		||||
    BACK_ITEM(MSG_CONFIGURATION);
 | 
			
		||||
    GCODES_ITEM(MSG_TOUCHMI_INIT, PSTR("M851 Z0\nG28\nG1 F200 Z0"));
 | 
			
		||||
    SUBMENU(MSG_ZPROBE_ZOFFSET, lcd_babystep_zoffset);
 | 
			
		||||
@@ -247,6 +250,7 @@ void menu_advanced_settings();
 | 
			
		||||
    GCODES_ITEM(MSG_TOUCHMI_ZTEST, PSTR("G28\nG1 F200 Z0"));
 | 
			
		||||
    END_MENU();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ENABLED(CONTROLLER_FAN_MENU)
 | 
			
		||||
@@ -342,6 +346,8 @@ void menu_advanced_settings();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void menu_configuration() {
 | 
			
		||||
  const bool busy = printer_busy();
 | 
			
		||||
 | 
			
		||||
  START_MENU();
 | 
			
		||||
  BACK_ITEM(MSG_MAIN);
 | 
			
		||||
 | 
			
		||||
@@ -367,7 +373,6 @@ void menu_configuration() {
 | 
			
		||||
    SUBMENU(MSG_CONTROLLER_FAN, menu_controller_fan);
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  const bool busy = printer_busy();
 | 
			
		||||
  if (!busy) {
 | 
			
		||||
    #if EITHER(DELTA_CALIBRATION_MENU, DELTA_AUTO_CALIBRATION)
 | 
			
		||||
      SUBMENU(MSG_DELTA_CALIBRATE, menu_delta_calibrate);
 | 
			
		||||
@@ -435,8 +440,7 @@ void menu_configuration() {
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(EEPROM_SETTINGS)
 | 
			
		||||
    ACTION_ITEM(MSG_STORE_EEPROM, lcd_store_settings);
 | 
			
		||||
    if (!busy)
 | 
			
		||||
      ACTION_ITEM(MSG_LOAD_EEPROM, lcd_load_settings);
 | 
			
		||||
    if (!busy) ACTION_ITEM(MSG_LOAD_EEPROM, lcd_load_settings);
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  if (!busy)
 | 
			
		||||
 
 | 
			
		||||
@@ -118,6 +118,8 @@ void lcd_delta_settings() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void menu_delta_calibrate() {
 | 
			
		||||
  const bool all_homed = all_axes_homed();
 | 
			
		||||
 | 
			
		||||
  START_MENU();
 | 
			
		||||
  BACK_ITEM(MSG_MAIN);
 | 
			
		||||
 | 
			
		||||
@@ -133,7 +135,7 @@ void menu_delta_calibrate() {
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(DELTA_CALIBRATION_MENU)
 | 
			
		||||
    SUBMENU(MSG_AUTO_HOME, _lcd_delta_calibrate_home);
 | 
			
		||||
    if (all_axes_homed()) {
 | 
			
		||||
    if (all_homed) {
 | 
			
		||||
      SUBMENU(MSG_DELTA_CALIBRATE_X, _goto_tower_x);
 | 
			
		||||
      SUBMENU(MSG_DELTA_CALIBRATE_Y, _goto_tower_y);
 | 
			
		||||
      SUBMENU(MSG_DELTA_CALIBRATE_Z, _goto_tower_z);
 | 
			
		||||
 
 | 
			
		||||
@@ -95,26 +95,37 @@ void _menu_temp_filament_op(const PauseMode mode, const int8_t extruder) {
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#if E_STEPPERS > 1 || ENABLED(FILAMENT_LOAD_UNLOAD_GCODES)
 | 
			
		||||
  void menu_change_filament() {
 | 
			
		||||
    START_MENU();
 | 
			
		||||
    BACK_ITEM(MSG_MAIN);
 | 
			
		||||
 | 
			
		||||
  void menu_change_filament() {
 | 
			
		||||
    // Say "filament change" when no print is active
 | 
			
		||||
    editable.int8 = printingIsPaused() ? PAUSE_MODE_PAUSE_PRINT : PAUSE_MODE_CHANGE_FILAMENT;
 | 
			
		||||
 | 
			
		||||
    #if E_STEPPERS > 1 && ENABLED(FILAMENT_UNLOAD_ALL_EXTRUDERS)
 | 
			
		||||
      bool too_cold = false;
 | 
			
		||||
      for (uint8_t s = 0; !too_cold && s < E_STEPPERS; s++)
 | 
			
		||||
        too_cold = thermalManager.targetTooColdToExtrude(s);
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES)
 | 
			
		||||
      const bool is_busy = printer_busy();
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    START_MENU();
 | 
			
		||||
    BACK_ITEM(MSG_MAIN);
 | 
			
		||||
 | 
			
		||||
    // Change filament
 | 
			
		||||
    #if E_STEPPERS == 1
 | 
			
		||||
      PGM_P const msg = GET_TEXT(MSG_FILAMENTCHANGE);
 | 
			
		||||
      if (thermalManager.targetTooColdToExtrude(active_extruder))
 | 
			
		||||
      MENU_ITEM_IF (thermalManager.targetTooColdToExtrude(active_extruder))
 | 
			
		||||
        SUBMENU_P(msg, []{ _menu_temp_filament_op(PAUSE_MODE_CHANGE_FILAMENT, 0); });
 | 
			
		||||
      else
 | 
			
		||||
      MENU_ITEM_ELSE
 | 
			
		||||
        GCODES_ITEM_P(msg, PSTR("M600 B0"));
 | 
			
		||||
    #else
 | 
			
		||||
      PGM_P const msg = GET_TEXT(MSG_FILAMENTCHANGE_E);
 | 
			
		||||
      LOOP_L_N(s, E_STEPPERS) {
 | 
			
		||||
        if (thermalManager.targetTooColdToExtrude(s))
 | 
			
		||||
        MENU_ITEM_IF (thermalManager.targetTooColdToExtrude(s))
 | 
			
		||||
          SUBMENU_N_P(s, msg, []{ _menu_temp_filament_op(PAUSE_MODE_CHANGE_FILAMENT, MenuItemBase::itemIndex); });
 | 
			
		||||
        else {
 | 
			
		||||
        MENU_ITEM_ELSE {
 | 
			
		||||
          ACTION_ITEM_N_P(s, msg, []{
 | 
			
		||||
            char cmd[13];
 | 
			
		||||
            sprintf_P(cmd, PSTR("M600 B0 T%i"), int(MenuItemBase::itemIndex));
 | 
			
		||||
@@ -125,20 +136,20 @@ void _menu_temp_filament_op(const PauseMode mode, const int8_t extruder) {
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(FILAMENT_LOAD_UNLOAD_GCODES)
 | 
			
		||||
      if (!printer_busy()) {
 | 
			
		||||
      if (!is_busy) {
 | 
			
		||||
        // Load filament
 | 
			
		||||
        #if E_STEPPERS == 1
 | 
			
		||||
          PGM_P const msg_load = GET_TEXT(MSG_FILAMENTLOAD);
 | 
			
		||||
          if (thermalManager.targetTooColdToExtrude(active_extruder))
 | 
			
		||||
          MENU_ITEM_IF (thermalManager.targetTooColdToExtrude(active_extruder))
 | 
			
		||||
            SUBMENU_P(msg_load, []{ _menu_temp_filament_op(PAUSE_MODE_LOAD_FILAMENT, 0); });
 | 
			
		||||
          else
 | 
			
		||||
          MENU_ITEM_ELSE
 | 
			
		||||
            GCODES_ITEM_P(msg_load, PSTR("M701"));
 | 
			
		||||
        #else
 | 
			
		||||
          PGM_P const msg_load = GET_TEXT(MSG_FILAMENTLOAD_E);
 | 
			
		||||
          LOOP_L_N(s, E_STEPPERS) {
 | 
			
		||||
            if (thermalManager.targetTooColdToExtrude(s))
 | 
			
		||||
            MENU_ITEM_IF (thermalManager.targetTooColdToExtrude(s))
 | 
			
		||||
              SUBMENU_N_P(s, msg_load, []{ _menu_temp_filament_op(PAUSE_MODE_LOAD_FILAMENT, MenuItemBase::itemIndex); });
 | 
			
		||||
            else {
 | 
			
		||||
            MENU_ITEM_ELSE {
 | 
			
		||||
              ACTION_ITEM_N_P(s, msg_load, []{
 | 
			
		||||
                char cmd[12];
 | 
			
		||||
                sprintf_P(cmd, PSTR("M701 T%i"), int(MenuItemBase::itemIndex));
 | 
			
		||||
@@ -151,30 +162,22 @@ void _menu_temp_filament_op(const PauseMode mode, const int8_t extruder) {
 | 
			
		||||
        // Unload filament
 | 
			
		||||
        #if E_STEPPERS == 1
 | 
			
		||||
          PGM_P const msg_unload = GET_TEXT(MSG_FILAMENTUNLOAD);
 | 
			
		||||
          if (thermalManager.targetTooColdToExtrude(active_extruder))
 | 
			
		||||
          MENU_ITEM_IF (thermalManager.targetTooColdToExtrude(active_extruder))
 | 
			
		||||
            SUBMENU_P(msg_unload, []{ _menu_temp_filament_op(PAUSE_MODE_UNLOAD_FILAMENT, 0); });
 | 
			
		||||
          else
 | 
			
		||||
          MENU_ITEM_ELSE
 | 
			
		||||
            GCODES_ITEM_P(msg_unload, PSTR("M702"));
 | 
			
		||||
        #else
 | 
			
		||||
          #if ENABLED(FILAMENT_UNLOAD_ALL_EXTRUDERS)
 | 
			
		||||
          {
 | 
			
		||||
            bool too_cold = false;
 | 
			
		||||
            LOOP_L_N(s, E_STEPPERS) {
 | 
			
		||||
              if (thermalManager.targetTooColdToExtrude(s)) {
 | 
			
		||||
                too_cold = true; break;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            if (!too_cold)
 | 
			
		||||
              GCODES_ITEM(MSG_FILAMENTUNLOAD_ALL, PSTR("M702"));
 | 
			
		||||
            else
 | 
			
		||||
            MENU_ITEM_IF (too_cold)
 | 
			
		||||
              SUBMENU(MSG_FILAMENTUNLOAD_ALL, []{ _menu_temp_filament_op(PAUSE_MODE_UNLOAD_FILAMENT, -1); });
 | 
			
		||||
          }
 | 
			
		||||
            MENU_ITEM_ELSE
 | 
			
		||||
              GCODES_ITEM(MSG_FILAMENTUNLOAD_ALL, PSTR("M702"));
 | 
			
		||||
          #endif
 | 
			
		||||
          PGM_P const msg_unload = GET_TEXT(MSG_FILAMENTUNLOAD_E);
 | 
			
		||||
          LOOP_L_N(s, E_STEPPERS) {
 | 
			
		||||
            if (thermalManager.targetTooColdToExtrude(s))
 | 
			
		||||
            MENU_ITEM_IF (thermalManager.targetTooColdToExtrude(s))
 | 
			
		||||
              SUBMENU_N_P(s, msg_unload, []{ _menu_temp_filament_op(PAUSE_MODE_UNLOAD_FILAMENT, MenuItemBase::itemIndex); });
 | 
			
		||||
            else {
 | 
			
		||||
            MENU_ITEM_ELSE {
 | 
			
		||||
              ACTION_ITEM_N_P(s, msg_unload, []{
 | 
			
		||||
                char cmd[12];
 | 
			
		||||
                sprintf_P(cmd, PSTR("M702 T%i"), int(MenuItemBase::itemIndex));
 | 
			
		||||
@@ -194,12 +197,9 @@ static uint8_t hotend_status_extruder = 0;
 | 
			
		||||
 | 
			
		||||
static PGM_P pause_header() {
 | 
			
		||||
  switch (pause_mode) {
 | 
			
		||||
    case PAUSE_MODE_CHANGE_FILAMENT:
 | 
			
		||||
      return GET_TEXT(MSG_FILAMENT_CHANGE_HEADER);
 | 
			
		||||
    case PAUSE_MODE_LOAD_FILAMENT:
 | 
			
		||||
      return GET_TEXT(MSG_FILAMENT_CHANGE_HEADER_LOAD);
 | 
			
		||||
    case PAUSE_MODE_UNLOAD_FILAMENT:
 | 
			
		||||
      return GET_TEXT(MSG_FILAMENT_CHANGE_HEADER_UNLOAD);
 | 
			
		||||
    case PAUSE_MODE_CHANGE_FILAMENT:  return GET_TEXT(MSG_FILAMENT_CHANGE_HEADER);
 | 
			
		||||
    case PAUSE_MODE_LOAD_FILAMENT:    return GET_TEXT(MSG_FILAMENT_CHANGE_HEADER_LOAD);
 | 
			
		||||
    case PAUSE_MODE_UNLOAD_FILAMENT:  return GET_TEXT(MSG_FILAMENT_CHANGE_HEADER_UNLOAD);
 | 
			
		||||
    default: break;
 | 
			
		||||
  }
 | 
			
		||||
  return GET_TEXT(MSG_FILAMENT_CHANGE_HEADER_PAUSE);
 | 
			
		||||
@@ -227,11 +227,18 @@ void menu_pause_option() {
 | 
			
		||||
    STATIC_ITEM(MSG_FILAMENT_CHANGE_OPTION_HEADER);
 | 
			
		||||
  #endif
 | 
			
		||||
  ACTION_ITEM(MSG_FILAMENT_CHANGE_OPTION_PURGE, []{ pause_menu_response = PAUSE_RESPONSE_EXTRUDE_MORE; });
 | 
			
		||||
 | 
			
		||||
  #if HAS_FILAMENT_SENSOR
 | 
			
		||||
    if (runout.filament_ran_out)
 | 
			
		||||
    const bool still_out = runout.filament_ran_out;
 | 
			
		||||
    MENU_ITEM_IF (still_out)
 | 
			
		||||
      EDIT_ITEM(bool, MSG_RUNOUT_SENSOR, &runout.enabled, runout.reset);
 | 
			
		||||
  #else
 | 
			
		||||
    constexpr bool still_out = false;
 | 
			
		||||
  #endif
 | 
			
		||||
      ACTION_ITEM(MSG_FILAMENT_CHANGE_OPTION_RESUME, []{ pause_menu_response = PAUSE_RESPONSE_RESUME_PRINT; });
 | 
			
		||||
 | 
			
		||||
  MENU_ITEM_IF (!still_out)
 | 
			
		||||
    ACTION_ITEM(MSG_FILAMENT_CHANGE_OPTION_RESUME, []{ pause_menu_response = PAUSE_RESPONSE_RESUME_PRINT; });
 | 
			
		||||
 | 
			
		||||
  END_MENU();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -34,8 +34,8 @@
 | 
			
		||||
  #include "game/game.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define VALUE_ITEM(MSG, VALUE, STYL)    do{ char buffer[21]; strcpy_P(buffer, PSTR(": ")); strcpy(buffer + 2, VALUE); STATIC_ITEM(MSG, STYL, buffer); }while(0)
 | 
			
		||||
#define VALUE_ITEM_P(MSG, PVALUE, STYL) do{ char buffer[21]; strcpy_P(buffer, PSTR(": ")); strcpy_P(buffer + 2, PSTR(PVALUE)); STATIC_ITEM(MSG, STYL, buffer); }while(0)
 | 
			
		||||
#define VALUE_ITEM(MSG, VALUE, STYL)    do{ char msg[21]; strcpy_P(msg, PSTR(": ")); strcpy(msg + 2, VALUE); STATIC_ITEM(MSG, STYL, msg); }while(0)
 | 
			
		||||
#define VALUE_ITEM_P(MSG, PVALUE, STYL) do{ char msg[21]; strcpy_P(msg, PSTR(": ")); strcpy_P(msg + 2, PSTR(PVALUE)); STATIC_ITEM(MSG, STYL, msg); }while(0)
 | 
			
		||||
 | 
			
		||||
#if ENABLED(PRINTCOUNTER)
 | 
			
		||||
 | 
			
		||||
@@ -47,8 +47,6 @@
 | 
			
		||||
  void menu_info_stats() {
 | 
			
		||||
    if (ui.use_click()) return ui.go_back();
 | 
			
		||||
 | 
			
		||||
    char buffer[21];  // For macro usage
 | 
			
		||||
 | 
			
		||||
    printStatistics stats = print_job_timer.getStats();
 | 
			
		||||
 | 
			
		||||
    char buffer[21];
 | 
			
		||||
@@ -245,17 +243,13 @@ void menu_info_board() {
 | 
			
		||||
    STATIC_ITEM_P(PSTR(MACHINE_NAME));                          // My3DPrinter
 | 
			
		||||
    STATIC_ITEM_P(PSTR(WEBSITE_URL));                           // www.my3dprinter.com
 | 
			
		||||
    VALUE_ITEM_P(MSG_INFO_EXTRUDERS, STRINGIFY(EXTRUDERS), SS_CENTER); // Extruders: 2
 | 
			
		||||
    #if ENABLED(AUTO_BED_LEVELING_3POINT)
 | 
			
		||||
      STATIC_ITEM(MSG_3POINT_LEVELING);                         // 3-Point Leveling
 | 
			
		||||
    #elif ENABLED(AUTO_BED_LEVELING_LINEAR)
 | 
			
		||||
      STATIC_ITEM(MSG_LINEAR_LEVELING);                         // Linear Leveling
 | 
			
		||||
    #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
 | 
			
		||||
      STATIC_ITEM(MSG_BILINEAR_LEVELING);                       // Bi-linear Leveling
 | 
			
		||||
    #elif ENABLED(AUTO_BED_LEVELING_UBL)
 | 
			
		||||
      STATIC_ITEM(MSG_UBL_LEVELING);                            // Unified Bed Leveling
 | 
			
		||||
    #elif ENABLED(MESH_BED_LEVELING)
 | 
			
		||||
      STATIC_ITEM(MSG_MESH_LEVELING);                           // Mesh Leveling
 | 
			
		||||
    #endif
 | 
			
		||||
    STATIC_ITEM(
 | 
			
		||||
      TERN_(AUTO_BED_LEVELING_3POINT, MSG_3POINT_LEVELING)      // 3-Point Leveling
 | 
			
		||||
      TERN_(AUTO_BED_LEVELING_LINEAR, MSG_LINEAR_LEVELING)      // Linear Leveling
 | 
			
		||||
      TERN_(AUTO_BED_LEVELING_BILINEAR, MSG_BILINEAR_LEVELING)  // Bi-linear Leveling
 | 
			
		||||
      TERN_(AUTO_BED_LEVELING_UBL, MSG_UBL_LEVELING)            // Unified Bed Leveling
 | 
			
		||||
      TERN_(MESH_BED_LEVELING, MSG_MESH_LEVELING)               // Mesh Leveling
 | 
			
		||||
    );
 | 
			
		||||
    END_SCREEN();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -282,27 +276,26 @@ void menu_info() {
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if HAS_GAMES
 | 
			
		||||
  {
 | 
			
		||||
    #if ENABLED(GAMES_EASTER_EGG)
 | 
			
		||||
      SKIP_ITEM();
 | 
			
		||||
      SKIP_ITEM();
 | 
			
		||||
      SKIP_ITEM();
 | 
			
		||||
      SKIP_ITEM(); SKIP_ITEM(); SKIP_ITEM();
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    // Game sub-menu or the individual game
 | 
			
		||||
    {
 | 
			
		||||
      SUBMENU(
 | 
			
		||||
        #if HAS_GAME_MENU
 | 
			
		||||
          MSG_GAMES, menu_game
 | 
			
		||||
        #elif ENABLED(MARLIN_BRICKOUT)
 | 
			
		||||
          MSG_BRICKOUT, brickout.enter_game
 | 
			
		||||
        #elif ENABLED(MARLIN_INVADERS)
 | 
			
		||||
          MSG_INVADERS, invaders.enter_game
 | 
			
		||||
        #elif ENABLED(MARLIN_SNAKE)
 | 
			
		||||
          MSG_SNAKE, snake.enter_game
 | 
			
		||||
        #elif ENABLED(MARLIN_MAZE)
 | 
			
		||||
          MSG_MAZE, maze.enter_game
 | 
			
		||||
        #endif
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    SUBMENU(
 | 
			
		||||
      #if HAS_GAME_MENU
 | 
			
		||||
        MSG_GAMES, menu_game
 | 
			
		||||
      #elif ENABLED(MARLIN_BRICKOUT)
 | 
			
		||||
        MSG_BRICKOUT, brickout.enter_game
 | 
			
		||||
      #elif ENABLED(MARLIN_INVADERS)
 | 
			
		||||
        MSG_INVADERS, invaders.enter_game
 | 
			
		||||
      #elif ENABLED(MARLIN_SNAKE)
 | 
			
		||||
        MSG_SNAKE, snake.enter_game
 | 
			
		||||
      #elif ENABLED(MARLIN_MAZE)
 | 
			
		||||
        MSG_MAZE, maze.enter_game
 | 
			
		||||
      #endif
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  END_MENU();
 | 
			
		||||
 
 | 
			
		||||
@@ -70,8 +70,10 @@ void menu_led_custom() {
 | 
			
		||||
void menu_led() {
 | 
			
		||||
  START_MENU();
 | 
			
		||||
  BACK_ITEM(MSG_MAIN);
 | 
			
		||||
  bool led_on = leds.lights_on;
 | 
			
		||||
  EDIT_ITEM(bool, MSG_LEDS, &led_on, leds.toggle);
 | 
			
		||||
  MENU_ITEM_IF(1) {
 | 
			
		||||
    bool led_on = leds.lights_on;
 | 
			
		||||
    EDIT_ITEM(bool, MSG_LEDS, &led_on, leds.toggle);
 | 
			
		||||
  }
 | 
			
		||||
  ACTION_ITEM(MSG_SET_LEDS_DEFAULT, leds.set_default);
 | 
			
		||||
  #if ENABLED(LED_COLOR_PRESETS)
 | 
			
		||||
    SUBMENU(MSG_LED_PRESETS, menu_led_presets);
 | 
			
		||||
 
 | 
			
		||||
@@ -84,9 +84,6 @@ void menu_configuration();
 | 
			
		||||
extern const char M21_STR[];
 | 
			
		||||
 | 
			
		||||
void menu_main() {
 | 
			
		||||
  START_MENU();
 | 
			
		||||
  BACK_ITEM(MSG_INFO_SCREEN);
 | 
			
		||||
 | 
			
		||||
  const bool busy = printingIsActive()
 | 
			
		||||
    #if ENABLED(SDSUPPORT)
 | 
			
		||||
      , card_detected = card.isMounted()
 | 
			
		||||
@@ -94,6 +91,9 @@ void menu_main() {
 | 
			
		||||
    #endif
 | 
			
		||||
  ;
 | 
			
		||||
 | 
			
		||||
  START_MENU();
 | 
			
		||||
  BACK_ITEM(MSG_INFO_SCREEN);
 | 
			
		||||
 | 
			
		||||
  if (busy) {
 | 
			
		||||
    #if MACHINE_CAN_PAUSE
 | 
			
		||||
      ACTION_ITEM(MSG_PAUSE_PRINT, ui.pause_print);
 | 
			
		||||
@@ -119,7 +119,7 @@ void menu_main() {
 | 
			
		||||
      // Autostart
 | 
			
		||||
      //
 | 
			
		||||
      #if ENABLED(MENU_ADDAUTOSTART)
 | 
			
		||||
        if (!busy) ACTION_ITEM(MSG_AUTOSTART, card.beginautostart);
 | 
			
		||||
        ACTION_ITEM(MSG_AUTOSTART, card.beginautostart);
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
      if (card_detected) {
 | 
			
		||||
@@ -144,7 +144,7 @@ void menu_main() {
 | 
			
		||||
 | 
			
		||||
    #endif // !HAS_ENCODER_WHEEL && SDSUPPORT
 | 
			
		||||
 | 
			
		||||
    if (TERN0(MACHINE_CAN_PAUSE, printingIsPaused()))
 | 
			
		||||
    MENU_ITEM_IF (TERN0(MACHINE_CAN_PAUSE, printingIsPaused()))
 | 
			
		||||
      ACTION_ITEM(MSG_RESUME_PRINT, ui.resume_print);
 | 
			
		||||
 | 
			
		||||
    SUBMENU(MSG_MOTION, menu_motion);
 | 
			
		||||
@@ -176,9 +176,9 @@ void menu_main() {
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(ADVANCED_PAUSE_FEATURE)
 | 
			
		||||
    #if E_STEPPERS == 1 && DISABLED(FILAMENT_LOAD_UNLOAD_GCODES)
 | 
			
		||||
      if (thermalManager.targetHotEnoughToExtrude(active_extruder))
 | 
			
		||||
      MENU_ITEM_IF (thermalManager.targetHotEnoughToExtrude(active_extruder))
 | 
			
		||||
        GCODES_ITEM(MSG_FILAMENTCHANGE, PSTR("M600 B0"));
 | 
			
		||||
      else
 | 
			
		||||
      MENU_ITEM_ELSE
 | 
			
		||||
        SUBMENU(MSG_FILAMENTCHANGE, []{ _menu_temp_filament_op(PAUSE_MODE_CHANGE_FILAMENT, 0); });
 | 
			
		||||
    #else
 | 
			
		||||
      SUBMENU(MSG_FILAMENTCHANGE, menu_change_filament);
 | 
			
		||||
@@ -197,41 +197,44 @@ void menu_main() {
 | 
			
		||||
  // Switch power on/off
 | 
			
		||||
  //
 | 
			
		||||
  #if ENABLED(PSU_CONTROL)
 | 
			
		||||
    if (powersupply_on)
 | 
			
		||||
    MENU_ITEM_IF (powersupply_on)
 | 
			
		||||
      GCODES_ITEM(MSG_SWITCH_PS_OFF, PSTR("M81"));
 | 
			
		||||
    else
 | 
			
		||||
    MENU_ITEM_ELSE
 | 
			
		||||
      GCODES_ITEM(MSG_SWITCH_PS_ON, PSTR("M80"));
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if BOTH(HAS_ENCODER_WHEEL, SDSUPPORT)
 | 
			
		||||
 | 
			
		||||
    // *** IF THIS SECTION IS CHANGED, REPRODUCE ABOVE ***
 | 
			
		||||
    if (!busy) {
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // Autostart
 | 
			
		||||
    //
 | 
			
		||||
    #if ENABLED(MENU_ADDAUTOSTART)
 | 
			
		||||
      if (!busy) ACTION_ITEM(MSG_AUTOSTART, card.beginautostart);
 | 
			
		||||
    #endif
 | 
			
		||||
      // *** IF THIS SECTION IS CHANGED, REPRODUCE ABOVE ***
 | 
			
		||||
 | 
			
		||||
    if (card_detected) {
 | 
			
		||||
      if (!card_open) {
 | 
			
		||||
        MENU_ITEM(gcode,
 | 
			
		||||
          #if PIN_EXISTS(SD_DETECT)
 | 
			
		||||
            MSG_CHANGE_MEDIA, M21_STR
 | 
			
		||||
          #else
 | 
			
		||||
            MSG_RELEASE_MEDIA, PSTR("M22")
 | 
			
		||||
          #endif
 | 
			
		||||
        );
 | 
			
		||||
        SUBMENU(MSG_MEDIA_MENU, menu_media);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      #if PIN_EXISTS(SD_DETECT)
 | 
			
		||||
        ACTION_ITEM(MSG_NO_MEDIA, nullptr);
 | 
			
		||||
      #else
 | 
			
		||||
        GCODES_ITEM(MSG_ATTACH_MEDIA, M21_STR);
 | 
			
		||||
      //
 | 
			
		||||
      // Autostart
 | 
			
		||||
      //
 | 
			
		||||
      #if ENABLED(MENU_ADDAUTOSTART)
 | 
			
		||||
        ACTION_ITEM(MSG_AUTOSTART, card.beginautostart);
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
      if (card_detected) {
 | 
			
		||||
        if (!card_open) {
 | 
			
		||||
          MENU_ITEM(gcode,
 | 
			
		||||
            #if PIN_EXISTS(SD_DETECT)
 | 
			
		||||
              MSG_CHANGE_MEDIA, M21_STR
 | 
			
		||||
            #else
 | 
			
		||||
              MSG_RELEASE_MEDIA, PSTR("M22")
 | 
			
		||||
            #endif
 | 
			
		||||
          );
 | 
			
		||||
          SUBMENU(MSG_MEDIA_MENU, menu_media);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        #if PIN_EXISTS(SD_DETECT)
 | 
			
		||||
          ACTION_ITEM(MSG_NO_MEDIA, nullptr);
 | 
			
		||||
        #else
 | 
			
		||||
          GCODES_ITEM(MSG_ATTACH_MEDIA, M21_STR);
 | 
			
		||||
        #endif
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  #endif // HAS_ENCODER_WHEEL && SDSUPPORT
 | 
			
		||||
 
 | 
			
		||||
@@ -45,25 +45,11 @@ void lcd_sd_updir() {
 | 
			
		||||
 | 
			
		||||
  void MarlinUI::reselect_last_file() {
 | 
			
		||||
    if (sd_encoder_position == 0xFFFF) return;
 | 
			
		||||
    //#if HAS_GRAPHICAL_LCD
 | 
			
		||||
    //  // This is a hack to force a screen update.
 | 
			
		||||
    //  ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
 | 
			
		||||
    //  ui.synchronize();
 | 
			
		||||
    //  safe_delay(50);
 | 
			
		||||
    //  ui.synchronize();
 | 
			
		||||
    //  ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
 | 
			
		||||
    //  ui.drawing_screen = ui.screen_changed = true;
 | 
			
		||||
    //#endif
 | 
			
		||||
 | 
			
		||||
    goto_screen(menu_media, sd_encoder_position, sd_top_line, sd_items);
 | 
			
		||||
    sd_encoder_position = 0xFFFF;
 | 
			
		||||
 | 
			
		||||
    defer_status_screen();
 | 
			
		||||
 | 
			
		||||
    //#if HAS_GRAPHICAL_LCD
 | 
			
		||||
    //  update();
 | 
			
		||||
    //#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
inline void sdcard_start_selected_file() {
 | 
			
		||||
@@ -141,14 +127,13 @@ void menu_media() {
 | 
			
		||||
  if (ui.should_draw()) for (uint16_t i = 0; i < fileCnt; i++) {
 | 
			
		||||
    if (_menuLineNr == _thisItemNr) {
 | 
			
		||||
      card.getfilename_sorted(SD_ORDER(i, fileCnt));
 | 
			
		||||
      if (card.flag.filenameIsDir)
 | 
			
		||||
      MENU_ITEM_IF (card.flag.filenameIsDir)
 | 
			
		||||
        MENU_ITEM(sdfolder, MSG_MEDIA_MENU, card);
 | 
			
		||||
      else
 | 
			
		||||
      MENU_ITEM_ELSE
 | 
			
		||||
        MENU_ITEM(sdfile, MSG_MEDIA_MENU, card);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    else
 | 
			
		||||
      SKIP_ITEM();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  END_MENU();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -193,6 +193,11 @@ void _goto_manual_move(const float scale) {
 | 
			
		||||
 | 
			
		||||
void _menu_move_distance(const AxisEnum axis, const screenFunc_t func, const int8_t eindex=-1) {
 | 
			
		||||
  _manual_move_func_ptr = func;
 | 
			
		||||
  #if ENABLED(PREVENT_COLD_EXTRUSION)
 | 
			
		||||
    const bool too_cold = axis == E_AXIS && thermalManager.tooColdToExtrude(eindex >= 0 ? eindex : active_extruder);
 | 
			
		||||
  #else
 | 
			
		||||
    constexpr bool too_cold = false;
 | 
			
		||||
  #endif
 | 
			
		||||
  START_MENU();
 | 
			
		||||
  if (LCD_HEIGHT >= 4) {
 | 
			
		||||
    switch (axis) {
 | 
			
		||||
@@ -205,24 +210,17 @@ void _menu_move_distance(const AxisEnum axis, const screenFunc_t func, const int
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  #if ENABLED(PREVENT_COLD_EXTRUSION)
 | 
			
		||||
    if (axis == E_AXIS && thermalManager.tooColdToExtrude(eindex >= 0 ? eindex : active_extruder))
 | 
			
		||||
      BACK_ITEM(MSG_HOTEND_TOO_COLD);
 | 
			
		||||
    else
 | 
			
		||||
  #endif
 | 
			
		||||
  {
 | 
			
		||||
  if (too_cold)
 | 
			
		||||
    BACK_ITEM(MSG_HOTEND_TOO_COLD);
 | 
			
		||||
  else {
 | 
			
		||||
    BACK_ITEM(MSG_MOVE_AXIS);
 | 
			
		||||
    SUBMENU(MSG_MOVE_10MM, []{ _goto_manual_move(10);    });
 | 
			
		||||
    SUBMENU(MSG_MOVE_1MM,  []{ _goto_manual_move( 1);    });
 | 
			
		||||
    SUBMENU(MSG_MOVE_01MM, []{ _goto_manual_move( 0.1f); });
 | 
			
		||||
    if (axis == Z_AXIS && (SHORT_MANUAL_Z_MOVE) > 0.0f && (SHORT_MANUAL_Z_MOVE) < 0.1f) {
 | 
			
		||||
    MENU_ITEM_IF (axis == Z_AXIS && (SHORT_MANUAL_Z_MOVE) > 0.0f && (SHORT_MANUAL_Z_MOVE) < 0.1f) {
 | 
			
		||||
      extern const char NUL_STR[];
 | 
			
		||||
      SUBMENU_P(NUL_STR, []{ _goto_manual_move(float(SHORT_MANUAL_Z_MOVE)); });
 | 
			
		||||
      MENU_ITEM_ADDON_START(0
 | 
			
		||||
        #if HAS_CHARACTER_LCD
 | 
			
		||||
          + 1
 | 
			
		||||
        #endif
 | 
			
		||||
      );
 | 
			
		||||
      MENU_ITEM_ADDON_START(0 + ENABLED(HAS_CHARACTER_LCD));
 | 
			
		||||
        char tmp[20], numstr[10];
 | 
			
		||||
        // Determine digits needed right of decimal
 | 
			
		||||
        const uint8_t digs = !UNEAR_ZERO((SHORT_MANUAL_Z_MOVE) * 1000 - int((SHORT_MANUAL_Z_MOVE) * 1000)) ? 4 :
 | 
			
		||||
@@ -273,23 +271,23 @@ void menu_move() {
 | 
			
		||||
      }
 | 
			
		||||
    #elif EXTRUDERS == 3
 | 
			
		||||
      if (active_extruder < 2) {
 | 
			
		||||
        if (active_extruder)
 | 
			
		||||
        MENU_ITEM_IF (active_extruder)
 | 
			
		||||
          GCODES_ITEM_N(0, MSG_SELECT_E, PSTR("T0"));
 | 
			
		||||
        else
 | 
			
		||||
        MENU_ITEM_ELSE
 | 
			
		||||
          GCODES_ITEM_N(1, MSG_SELECT_E, PSTR("T1"));
 | 
			
		||||
      }
 | 
			
		||||
    #else
 | 
			
		||||
      if (active_extruder)
 | 
			
		||||
      MENU_ITEM_IF (active_extruder)
 | 
			
		||||
        GCODES_ITEM_N(0, MSG_SELECT_E, PSTR("T0"));
 | 
			
		||||
      else
 | 
			
		||||
      MENU_ITEM_ELSE
 | 
			
		||||
        GCODES_ITEM_N(1, MSG_SELECT_E, PSTR("T1"));
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
  #elif ENABLED(DUAL_X_CARRIAGE)
 | 
			
		||||
 | 
			
		||||
    if (active_extruder)
 | 
			
		||||
    MENU_ITEM_IF (active_extruder)
 | 
			
		||||
      GCODES_ITEM_N(0, MSG_SELECT_E, PSTR("T0"));
 | 
			
		||||
    else
 | 
			
		||||
    MENU_ITEM_ELSE
 | 
			
		||||
      GCODES_ITEM_N(1, MSG_SELECT_E, PSTR("T1"));
 | 
			
		||||
 | 
			
		||||
  #endif
 | 
			
		||||
@@ -304,10 +302,8 @@ void menu_move() {
 | 
			
		||||
    #if EITHER(SWITCHING_EXTRUDER, SWITCHING_NOZZLE)
 | 
			
		||||
 | 
			
		||||
      // ...and the non-switching
 | 
			
		||||
      #if E_MANUAL == 5
 | 
			
		||||
        SUBMENU_MOVE_E(4);
 | 
			
		||||
      #elif E_MANUAL == 3
 | 
			
		||||
        SUBMENU_MOVE_E(2);
 | 
			
		||||
      #if E_MANUAL == 7 || E_MANUAL == 5 || E_MANUAL == 3
 | 
			
		||||
        SUBMENU_MOVE_E(E_MANUAL - 1);
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
    #elif MULTI_MANUAL
 | 
			
		||||
@@ -339,10 +335,8 @@ void menu_motion() {
 | 
			
		||||
  //
 | 
			
		||||
  // Move Axis
 | 
			
		||||
  //
 | 
			
		||||
  #if ENABLED(DELTA)
 | 
			
		||||
    if (all_axes_homed())
 | 
			
		||||
  #endif
 | 
			
		||||
      SUBMENU(MSG_MOVE_AXIS, menu_move);
 | 
			
		||||
  MENU_ITEM_IF (TERN1(DELTA, all_axes_homed()))
 | 
			
		||||
    SUBMENU(MSG_MOVE_AXIS, menu_move);
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Auto Home
 | 
			
		||||
@@ -370,20 +364,25 @@ void menu_motion() {
 | 
			
		||||
 | 
			
		||||
  #elif ENABLED(LCD_BED_LEVELING)
 | 
			
		||||
 | 
			
		||||
    if (!g29_in_progress) SUBMENU(MSG_BED_LEVELING, menu_bed_leveling);
 | 
			
		||||
    MENU_ITEM_IF (!g29_in_progress)
 | 
			
		||||
      SUBMENU(MSG_BED_LEVELING, menu_bed_leveling);
 | 
			
		||||
 | 
			
		||||
  #elif HAS_LEVELING && DISABLED(SLIM_LCD_MENUS)
 | 
			
		||||
 | 
			
		||||
    #if DISABLED(PROBE_MANUALLY)
 | 
			
		||||
      GCODES_ITEM(MSG_LEVEL_BED, PSTR("G28\nG29"));
 | 
			
		||||
    #endif
 | 
			
		||||
    if (all_axes_homed() && leveling_is_valid()) {
 | 
			
		||||
 | 
			
		||||
    MENU_ITEM_IF (all_axes_homed() && leveling_is_valid()) {
 | 
			
		||||
      bool show_state = planner.leveling_active;
 | 
			
		||||
      EDIT_ITEM(bool, MSG_BED_LEVELING, &show_state, _lcd_toggle_bed_leveling);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
 | 
			
		||||
      editable.decimal = planner.z_fade_height;
 | 
			
		||||
      EDIT_ITEM_FAST(float3, MSG_Z_FADE_HEIGHT, &editable.decimal, 0, 100, []{ set_z_fade_height(editable.decimal); });
 | 
			
		||||
      MENU_ITEM_IF(1) {
 | 
			
		||||
        editable.decimal = planner.z_fade_height;
 | 
			
		||||
        EDIT_ITEM_FAST(float3, MSG_Z_FADE_HEIGHT, &editable.decimal, 0, 100, []{ set_z_fade_height(editable.decimal); });
 | 
			
		||||
      }
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
  #endif
 | 
			
		||||
 
 | 
			
		||||
@@ -34,18 +34,19 @@
 | 
			
		||||
 | 
			
		||||
  void menu_spindle_laser() {
 | 
			
		||||
 | 
			
		||||
    const bool can_disable = cutter.enabled() && cutter.isOn;
 | 
			
		||||
 | 
			
		||||
    START_MENU();
 | 
			
		||||
    BACK_ITEM(MSG_MAIN);
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(SPINDLE_LASER_PWM)
 | 
			
		||||
      EDIT_ITEM_FAST(CUTTER_MENU_POWER_TYPE, MSG_CUTTER(POWER), &cutter.setPower, cutter.interpret_power(SPEED_POWER_MIN), cutter.interpret_power(SPEED_POWER_MAX),
 | 
			
		||||
      []{
 | 
			
		||||
        if (cutter.isOn) {
 | 
			
		||||
          cutter.power = cutter.setPower;
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      EDIT_ITEM_FAST( CUTTER_MENU_POWER_TYPE, MSG_CUTTER(POWER), &cutter.setPower
 | 
			
		||||
                    , cutter.interpret_power(SPEED_POWER_MIN), cutter.interpret_power(SPEED_POWER_MAX)
 | 
			
		||||
                    , []{ if (cutter.isOn) cutter.power = cutter.setPower; }
 | 
			
		||||
      );
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    if (cutter.enabled() && cutter.isOn)
 | 
			
		||||
    if (can_disable)
 | 
			
		||||
      ACTION_ITEM(MSG_CUTTER(OFF), cutter.disable);
 | 
			
		||||
    else {
 | 
			
		||||
      ACTION_ITEM(MSG_CUTTER(ON), cutter.enable_forward);
 | 
			
		||||
 
 | 
			
		||||
@@ -197,8 +197,10 @@ void menu_temperature() {
 | 
			
		||||
 | 
			
		||||
    #if HAS_FAN1 || HAS_FAN2 || HAS_FAN3 || HAS_FAN4 || HAS_FAN5 || HAS_FAN6 || HAS_FAN7
 | 
			
		||||
      auto fan_edit_items = [&](const uint8_t f) {
 | 
			
		||||
        editable.uint8 = thermalManager.fan_speed[f];
 | 
			
		||||
        EDIT_ITEM_FAST_N(percent, f, MSG_FAN_SPEED_N, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
        MENU_ITEM_IF(1) {
 | 
			
		||||
          editable.uint8 = thermalManager.fan_speed[f];
 | 
			
		||||
          EDIT_ITEM_FAST_N(percent, f, MSG_FAN_SPEED_N, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
        }
 | 
			
		||||
        #if ENABLED(EXTRA_FAN_SPEED)
 | 
			
		||||
          EDIT_ITEM_FAST_N(percent, f, MSG_EXTRA_FAN_SPEED_N, &thermalManager.new_fan_speed[f], 3, 255);
 | 
			
		||||
        #endif
 | 
			
		||||
@@ -208,14 +210,18 @@ void menu_temperature() {
 | 
			
		||||
    #define SNFAN(N) (ENABLED(SINGLENOZZLE) && !HAS_FAN##N && EXTRUDERS > N)
 | 
			
		||||
    #if SNFAN(1) || SNFAN(2) || SNFAN(3) || SNFAN(4) || SNFAN(5) || SNFAN(6) || SNFAN(7)
 | 
			
		||||
      auto singlenozzle_item = [&](const uint8_t f) {
 | 
			
		||||
        editable.uint8 = thermalManager.fan_speed[f];
 | 
			
		||||
        EDIT_ITEM_FAST_N(percent, f, MSG_STORED_FAN_N, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
        MENU_ITEM_IF(1) {
 | 
			
		||||
          editable.uint8 = thermalManager.fan_speed[f];
 | 
			
		||||
          EDIT_ITEM_FAST_N(percent, f, MSG_STORED_FAN_N, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    #if HAS_FAN0
 | 
			
		||||
      editable.uint8 = thermalManager.fan_speed[0];
 | 
			
		||||
      EDIT_ITEM_FAST_N(percent, 0, MSG_FIRST_FAN_SPEED, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
      MENU_ITEM_IF(1) {
 | 
			
		||||
        editable.uint8 = thermalManager.fan_speed[0];
 | 
			
		||||
        EDIT_ITEM_FAST_N(percent, 0, MSG_FIRST_FAN_SPEED, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
      }
 | 
			
		||||
      #if ENABLED(EXTRA_FAN_SPEED)
 | 
			
		||||
        EDIT_ITEM_FAST_N(percent, 0, MSG_FIRST_EXTRA_FAN_SPEED, &thermalManager.new_fan_speed[0], 3, 255);
 | 
			
		||||
      #endif
 | 
			
		||||
@@ -274,10 +280,12 @@ void menu_temperature() {
 | 
			
		||||
    //
 | 
			
		||||
    // Cooldown
 | 
			
		||||
    //
 | 
			
		||||
    bool has_heat = false;
 | 
			
		||||
    HOTEND_LOOP() if (thermalManager.temp_hotend[HOTEND_INDEX].target) { has_heat = true; break; }
 | 
			
		||||
    if (TERN0(HAS_HEATED_BED, thermalManager.temp_bed.target)) has_heat = true;
 | 
			
		||||
    if (has_heat) ACTION_ITEM(MSG_COOLDOWN, lcd_cooldown);
 | 
			
		||||
    MENU_ITEM_IF(1) {
 | 
			
		||||
      bool has_heat = false;
 | 
			
		||||
      HOTEND_LOOP() if (thermalManager.temp_hotend[HOTEND_INDEX].target) { has_heat = true; break; }
 | 
			
		||||
      if (TERN0(HAS_HEATED_BED, thermalManager.temp_bed.target)) has_heat = true;
 | 
			
		||||
      if (has_heat) ACTION_ITEM(MSG_COOLDOWN, lcd_cooldown);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  #endif // HAS_TEMP_HOTEND
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -146,8 +146,10 @@ void menu_tune() {
 | 
			
		||||
 | 
			
		||||
    #if HAS_FAN1 || HAS_FAN2 || HAS_FAN3 || HAS_FAN4 || HAS_FAN5 || HAS_FAN6 || HAS_FAN7
 | 
			
		||||
      auto fan_edit_items = [&](const uint8_t f) {
 | 
			
		||||
        editable.uint8 = thermalManager.fan_speed[f];
 | 
			
		||||
        EDIT_ITEM_FAST_N(percent, f, MSG_FAN_SPEED_N, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
        MENU_ITEM_IF(1) {
 | 
			
		||||
          editable.uint8 = thermalManager.fan_speed[f];
 | 
			
		||||
          EDIT_ITEM_FAST_N(percent, f, MSG_FAN_SPEED_N, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
        }
 | 
			
		||||
        #if ENABLED(EXTRA_FAN_SPEED)
 | 
			
		||||
          EDIT_ITEM_FAST_N(percent, f, MSG_EXTRA_FAN_SPEED_N, &thermalManager.new_fan_speed[f], 3, 255);
 | 
			
		||||
        #endif
 | 
			
		||||
@@ -157,14 +159,18 @@ void menu_tune() {
 | 
			
		||||
    #define SNFAN(N) (ENABLED(SINGLENOZZLE) && !HAS_FAN##N && EXTRUDERS > N)
 | 
			
		||||
    #if SNFAN(1) || SNFAN(2) || SNFAN(3) || SNFAN(4) || SNFAN(5) || SNFAN(6) || SNFAN(7)
 | 
			
		||||
      auto singlenozzle_item = [&](const uint8_t f) {
 | 
			
		||||
        editable.uint8 = thermalManager.fan_speed[f];
 | 
			
		||||
        EDIT_ITEM_FAST_N(percent, f, MSG_STORED_FAN_N, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
        MENU_ITEM_IF(1) {
 | 
			
		||||
          editable.uint8 = thermalManager.fan_speed[f];
 | 
			
		||||
          EDIT_ITEM_FAST_N(percent, f, MSG_STORED_FAN_N, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    #if HAS_FAN0
 | 
			
		||||
      editable.uint8 = thermalManager.fan_speed[0];
 | 
			
		||||
      EDIT_ITEM_FAST_N(percent, 0, MSG_FIRST_FAN_SPEED, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
      MENU_ITEM_IF(1) {
 | 
			
		||||
        editable.uint8 = thermalManager.fan_speed[0];
 | 
			
		||||
        EDIT_ITEM_FAST_N(percent, 0, MSG_FIRST_FAN_SPEED, &editable.uint8, 0, 255, on_fan_update);
 | 
			
		||||
      }
 | 
			
		||||
      #if ENABLED(EXTRA_FAN_SPEED)
 | 
			
		||||
        EDIT_ITEM_FAST_N(percent, 0, MSG_FIRST_EXTRA_FAN_SPEED, &thermalManager.new_fan_speed[0], 3, 255);
 | 
			
		||||
      #endif
 | 
			
		||||
 
 | 
			
		||||
@@ -376,9 +376,8 @@ void _lcd_ubl_storage_mesh() {
 | 
			
		||||
  int16_t a = settings.calc_num_meshes();
 | 
			
		||||
  START_MENU();
 | 
			
		||||
  BACK_ITEM(MSG_UBL_LEVEL_BED);
 | 
			
		||||
  if (!WITHIN(ubl_storage_slot, 0, a - 1)) {
 | 
			
		||||
  if (!WITHIN(ubl_storage_slot, 0, a - 1))
 | 
			
		||||
    STATIC_ITEM(MSG_UBL_NO_STORAGE);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    EDIT_ITEM(int3, MSG_UBL_STORAGE_SLOT, &ubl_storage_slot, 0, a - 1);
 | 
			
		||||
    ACTION_ITEM(MSG_UBL_LOAD_MESH, _lcd_ubl_load_mesh_cmd);
 | 
			
		||||
@@ -580,9 +579,9 @@ void _lcd_ubl_step_by_step() {
 | 
			
		||||
void _lcd_ubl_level_bed() {
 | 
			
		||||
  START_MENU();
 | 
			
		||||
  BACK_ITEM(MSG_MOTION);
 | 
			
		||||
  if (planner.leveling_active)
 | 
			
		||||
  MENU_ITEM_IF (planner.leveling_active)
 | 
			
		||||
    GCODES_ITEM(MSG_UBL_DEACTIVATE_MESH, PSTR("G29 D"));
 | 
			
		||||
  else
 | 
			
		||||
  MENU_ITEM_ELSE
 | 
			
		||||
    GCODES_ITEM(MSG_UBL_ACTIVATE_MESH, PSTR("G29 A"));
 | 
			
		||||
  SUBMENU(MSG_UBL_STEP_BY_STEP_MENU, _lcd_ubl_step_by_step);
 | 
			
		||||
  ACTION_ITEM(MSG_UBL_MESH_EDIT, _lcd_ubl_output_map_lcd_cmd);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user