From 4cfa9780b6855bb000e53aa2354e9f30026d535f Mon Sep 17 00:00:00 2001 From: supermerill Date: Sat, 23 Dec 2023 03:37:57 +0100 Subject: [PATCH] Fan cooling: move min_fan_speed to printer. fan_always_on changed to a real default_fan_speed - updated helper text. - now default will be used when a field is deactivated. - default_fan_speed =0 is a bit like the old fan_always_on to false. - min fan speed is a real min for fan speed (if not stopped) Should be easier to understand. supermerill/SuperSlicer#4009 --- resources/ui_layout/default/filament.ui | 11 +- resources/ui_layout/default/printer_fff.ui | 1 + src/libslic3r/GCode/CoolingBuffer.cpp | 63 +++-- src/libslic3r/GCode/CoolingBuffer.hpp | 2 +- src/libslic3r/Preset.cpp | 10 +- src/libslic3r/Print.cpp | 4 +- src/libslic3r/PrintConfig.cpp | 77 +++++- src/libslic3r/PrintConfig.hpp | 11 +- src/slic3r/GUI/PresetHints.cpp | 283 +++++++++++++-------- src/slic3r/GUI/PresetHints.hpp | 2 +- src/slic3r/GUI/Tab.cpp | 10 +- 11 files changed, 321 insertions(+), 153 deletions(-) diff --git a/resources/ui_layout/default/filament.ui b/resources/ui_layout/default/filament.ui index eeaa1973a75..5b9ad60732d 100644 --- a/resources/ui_layout/default/filament.ui +++ b/resources/ui_layout/default/filament.ui @@ -29,12 +29,7 @@ group:Print speed override page:Cooling:time group:Fan speed - default - setting:id$0:label$Run the fan at default speed when possible:fan_always_on - line:Disable fan for the first - setting:id$0:width$5:label$_:sidetext_width$7:disable_fan_first_layers - setting:id$0:width$5:label_width$12:full_fan_speed_layer - end_line - setting:id$0:min_fan_speed + setting:id$0:default_fan_speed line:Perimeter fan speed setting:id$0:label_width$12:label$Internal:perimeter_fan_speed setting:id$0:label_width$12:label$External:external_perimeter_fan_speed @@ -53,6 +48,10 @@ group:Fan speed - default setting:id$0:label_width$12:label$Overhangs:overhangs_fan_speed line:Gap fill fan speed setting:id$0:label_width$12:label$Gap fill:gap_fill_fan_speed + line:Disable fan for the first + setting:id$0:width$5:label$_:sidetext_width$7:disable_fan_first_layers + setting:id$0:width$5:label_width$12:full_fan_speed_layer + end_line group:Short layer time - began to increase base fan speed setting:id$0:fan_below_layer_time setting:id$0:label$Max fan speed:max_fan_speed diff --git a/resources/ui_layout/default/printer_fff.ui b/resources/ui_layout/default/printer_fff.ui index 5c016f12231..f7d8c48deae 100644 --- a/resources/ui_layout/default/printer_fff.ui +++ b/resources/ui_layout/default/printer_fff.ui @@ -38,6 +38,7 @@ group:silent_mode_event:Firmware end_line setting:gcode_filename_illegal_char group:Cooling fan + setting:fan_printer_min_speed line:Speedup time setting:label$:fan_speedup_time setting:label$Only for overhangs:fan_speedup_overhangs diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp index bbab10548c3..07d4e02c467 100644 --- a/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/src/libslic3r/GCode/CoolingBuffer.cpp @@ -857,14 +857,24 @@ std::string CoolingBuffer::apply_layer_cooldown( int fan_speeds[ExtrusionRole::erCount]; int default_fan_speed[ExtrusionRole::erCount]; #define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder) - int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed); + const int min_fan_speed = m_config.fan_printer_min_speed; + assert(min_fan_speed >= 0); + int initial_default_fan_speed = EXTRUDER_CONFIG(default_fan_speed); + //if default_fan_speed activated, be sure it's at least the mins + if (initial_default_fan_speed > 0 && initial_default_fan_speed < min_fan_speed) + initial_default_fan_speed = min_fan_speed; + // 0 was deprecated, replaced by 1: allow 1 to still be 0 (and it's now deprecated) + if (initial_default_fan_speed == 1) + initial_default_fan_speed = 0; + //initialise the speed array for (int i = 0; i < ExtrusionRole::erCount; i++) { fan_control[i] = false; fan_speeds[i] = 0; - default_fan_speed[i] = min_fan_speed; + default_fan_speed[i] = initial_default_fan_speed; // 0 was deprecated, replaced by 1: allow 1 to still be 0 (and it's now deprecated) if (default_fan_speed[i] == 1) default_fan_speed[i] = 0; } + //set the fan controls default_fan_speed[ExtrusionRole::erBridgeInfill] = EXTRUDER_CONFIG(bridge_fan_speed); default_fan_speed[ExtrusionRole::erInternalBridgeInfill] = EXTRUDER_CONFIG(bridge_internal_fan_speed); default_fan_speed[ExtrusionRole::erTopSolidInfill] = EXTRUDER_CONFIG(top_fan_speed); @@ -878,8 +888,17 @@ std::string CoolingBuffer::apply_layer_cooldown( default_fan_speed[ExtrusionRole::erInternalInfill] = EXTRUDER_CONFIG(infill_fan_speed); default_fan_speed[ExtrusionRole::erOverhangPerimeter] = EXTRUDER_CONFIG(overhangs_fan_speed); default_fan_speed[ExtrusionRole::erGapFill] = EXTRUDER_CONFIG(gap_fill_fan_speed); + // if default is enabled, it takes over the settings that are disabled. + if (initial_default_fan_speed >= 0) { + for (int i = 0; i < ExtrusionRole::erCount; i++) { + // this setting is disbaled. As default is not, it will use the default value + if (default_fan_speed[i] < 0) { + default_fan_speed[i] = initial_default_fan_speed; + } + } + } auto change_extruder_set_fan = [this, layer_id, layer_time, &new_gcode, - &fan_control, &fan_speeds, &default_fan_speed, &min_fan_speed]() + &fan_control, &fan_speeds, &default_fan_speed, initial_default_fan_speed, min_fan_speed]() { int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers); // Is the fan speed ramp enabled? @@ -891,8 +910,8 @@ std::string CoolingBuffer::apply_layer_cooldown( for (int i = 0; i < ExtrusionRole::erCount; i++) { fan_speeds[i] = default_fan_speed[i]; } - //if not always on, the default is "no fan" and not the min. - if (!EXTRUDER_CONFIG(fan_always_on)) { + //fan_speeds[0] carry the current default value. ensure it's not negative. + if (initial_default_fan_speed <= 0) { fan_speeds[0] = 0; } if (layer_time < slowdown_below_layer_time && fan_below_layer_time > 0) { @@ -925,13 +944,19 @@ std::string CoolingBuffer::apply_layer_cooldown( fan_speeds[idx] = std::clamp(int(float(fan_speeds[idx]) * factor + 0.01f), 0, 255); } } - //only activate fan control if the fan speed is higher than default - fan_control[0] = true; + //only activate fan control if the fan speed is higher than min + fan_control[0] = fan_speeds[0] >= 0; for (size_t i = 1; i < ExtrusionRole::erCount; i++) { - fan_control[i] = fan_speeds[i] >= 0 && fan_speeds[i] > fan_speeds[0]; + fan_control[i] = fan_speeds[i] >= 0; } - // if bridge_internal_fan is disabled, it takes the value of bridge_fan_control + // if bridge_fan is disabled, it takes the value of default_fan + if (!fan_control[ExtrusionRole::erBridgeInfill] && fan_control[0]) { + fan_control[ExtrusionRole::erBridgeInfill] = true; + fan_speeds[ExtrusionRole::erBridgeInfill] = fan_speeds[0]; + } + + // if bridge_internal_fan is disabled, it takes the value of bridge_fan if (!fan_control[ExtrusionRole::erInternalBridgeInfill] && fan_control[ExtrusionRole::erBridgeInfill]) { fan_control[ExtrusionRole::erInternalBridgeInfill] = true; fan_speeds[ExtrusionRole::erInternalBridgeInfill] = fan_speeds[ExtrusionRole::erBridgeInfill]; @@ -957,7 +982,13 @@ std::string CoolingBuffer::apply_layer_cooldown( fan_speeds[i] = 0; } } - if (fan_speeds[0] != m_fan_speed) { + // apply min fan speed, after the eventual speedup. + for (int i = 1; i < ExtrusionRole::erCount; i++) { + if (fan_control[i] && fan_speeds[i] > 0) { + fan_speeds[i] = std::max(fan_speeds[i], min_fan_speed); + } + } + if (fan_speeds[0] != m_fan_speed && fan_control[0]) { m_fan_speed = fan_speeds[0]; new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, m_fan_speed, EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage, @@ -968,7 +999,7 @@ std::string CoolingBuffer::apply_layer_cooldown( std::vector extrude_tree; const char *pos = gcode.c_str(); int current_feedrate = 0; - int stored_fan_speed = m_fan_speed; + int stored_fan_speed = m_fan_speed < 0 ? 0 : m_fan_speed; change_extruder_set_fan(); for (const CoolingLine *line : lines) { const char *line_start = gcode.c_str() + line->line_start; @@ -986,7 +1017,7 @@ std::string CoolingBuffer::apply_layer_cooldown( new_gcode.append(line_start, line_end - line_start); } } else if (line->type & CoolingLine::TYPE_STORE_FOR_WT) { - stored_fan_speed = m_fan_speed; + stored_fan_speed = m_fan_speed < 0 ? 0 : m_fan_speed; } else if (line->type & CoolingLine::TYPE_RESTORE_AFTER_WT) { new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, stored_fan_speed, EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage, @@ -1099,10 +1130,10 @@ std::string CoolingBuffer::apply_layer_cooldown( } } if (!fan_set) { - //return to default - new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, m_fan_speed, - EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage, - "set default fan"); + // return to default + new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, m_fan_speed < 0 ? 0 : m_fan_speed, + EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage, + "set default fan"); } fan_need_set = false; } diff --git a/src/libslic3r/GCode/CoolingBuffer.hpp b/src/libslic3r/GCode/CoolingBuffer.hpp index 1d1808073e1..0043e32e5a0 100644 --- a/src/libslic3r/GCode/CoolingBuffer.hpp +++ b/src/libslic3r/GCode/CoolingBuffer.hpp @@ -52,7 +52,7 @@ class CoolingBuffer { uint16_t m_num_extruders { 0 }; // Referencs GCode::m_config, which is FullPrintConfig. While the PrintObjectConfig slice of FullPrintConfig is being modified, // the PrintConfig slice of FullPrintConfig is constant, thus no thread synchronization is required. - const PrintConfig &m_config; + const FullPrintConfig &m_config; uint16_t m_current_extruder; //saved previous unslowed layer diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index edfe03f9206..df9e639bc84 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -747,10 +747,11 @@ static std::vector s_Preset_filament_options { "filament_dip_insertion_speed", "filament_dip_extraction_speed", //skinnydip params end "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", - // cooling - "fan_always_on", - "min_fan_speed", - "max_fan_speed", + // "cooling", + // "fan_always_on", (now default_fan_speed) + // "min_fan_speed", (now fan_printer_min_speed) + "default_fan_speed", + "max_fan_speed", "bridge_fan_speed", "bridge_internal_fan_speed", "external_perimeter_fan_speed", @@ -807,6 +808,7 @@ static std::vector s_Preset_printer_options { "fan_speedup_overhangs", "fan_speedup_time", "fan_percentage", + "fan_printer_min_speed", "gcode_filename_illegal_char", "gcode_flavor", "gcode_precision_xyz", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index ecf364e8b8b..75e588ede42 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -77,6 +77,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver& /* ne "complete_objects_sort", "cooling", "default_acceleration", + "default_fan_speed", "deretract_speed", "disable_fan_first_layers", "duplicate_distance", @@ -94,12 +95,12 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver& /* ne "extruder_fan_offset" "extruder_temperature_offset", "extrusion_multiplier", - "fan_always_on", "fan_below_layer_time", "fan_kickstart", "fan_speedup_overhangs", "fan_speedup_time", "fan_percentage", + "fan_printer_min_speed", "filament_colour", "filament_custom_variables", "filament_diameter", @@ -134,7 +135,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver& /* ne "max_print_height", "max_print_speed", "max_volumetric_speed", - "min_fan_speed", "min_length", "min_print_speed", "milling_toolchange_end_gcode", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index ed632aa99a5..a81ec9343d2 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -728,7 +728,7 @@ void PrintConfigDef::init_fff_params() def->label = L("Bridges fan speed"); def->category = OptionCategory::cooling; def->tooltip = L("This fan speed is enforced during bridges and overhangs. It won't slow down the fan if it's currently running at a higher speed." - "\nSet to -1 to disable this override (Bridge will use default fan speed)." + "\nSet to -1 to disable this override (Bridges will use default fan speed)." "\nCan be disabled by disable_fan_first_layers and increased by low layer time."); def->sidetext = L("%"); def->min = -1; @@ -741,8 +741,7 @@ void PrintConfigDef::init_fff_params() def->label = L("Infill bridges fan speed"); def->category = OptionCategory::cooling; def->tooltip = L("This fan speed is enforced during all infill bridges. It won't slow down the fan if it's currently running at a higher speed." - "\nSet to 1 to follow default speed." - "\nSet to -1 to disable this override (internal bridges will use Bridges fan speed)." + "\nSet to -1 to disable this override (Internal bridges will use Bridges fan speed)." "\nCan be disabled by disable_fan_first_layers and increased by low layer time."); def->sidetext = L("%"); def->min = -1; @@ -1211,6 +1210,20 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionStrings()); def->cli = ConfigOptionDef::nocli; + def = this->add("default_fan_speed", coInts); + def->label = L("Default fan speed"); + def->category = OptionCategory::cooling; + def->tooltip = L( + "Default speed for the fan, to set the speed for features where there is no fan control. Useful for PLA and other low-temp filament." + "\nSet 0 to disable the fan by default. Useful for ABS and other high-temp filaments." + "\nSet -1 to disable. if disabled, the beahavior isn't defined yet. The goal is to avoid adding fan speed commands."); + def->mode = comSimpleAE | comSuSi; + def->min = -1; + def->max = 100; + def->is_vector_extruder = true; + def->set_default_value(new ConfigOptionInts({-1})); + def->aliases = { "min_fan_speed" }; // only if "fan_always_on" + def = this->add("default_print_profile", coString); def->label = L("Default print profile"); def->tooltip = L("Default print profile associated with the current printer profile. " @@ -1814,6 +1827,8 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvancedE | comSuSi; def->set_default_value(new ConfigOptionFloatOrPercent(0, false, false)); +#if 0 + //not used anymore, to remove !! @DEPRECATED (replaces by default_fan_speed) def = this->add("fan_always_on", coBools); def->label = L("Keep fan always on"); def->category = OptionCategory::cooling; @@ -1822,6 +1837,7 @@ void PrintConfigDef::init_fff_params() def->mode = comSimpleAE | comPrusa; def->is_vector_extruder = true; def->set_default_value(new ConfigOptionBools{ true }); +#endif def = this->add("fan_below_layer_time", coFloats); def->label = L("Enable fan if layer print time is below"); @@ -3672,6 +3688,8 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert | comPrusa; def->set_default_value(new ConfigOptionFloat(0)); +#if 0 + // replaced by fan_printer_min_speed, to remove !! @DEPRECATED def = this->add("min_fan_speed", coInts); def->label = L("Default fan speed"); def->full_label = L("Default fan speed"); @@ -3683,6 +3701,7 @@ void PrintConfigDef::init_fff_params() def->mode = comSimpleAE | comPrusa; def->is_vector_extruder = true; def->set_default_value(new ConfigOptionInts{ 35 }); +#endif def = this->add("fan_percentage", coBool); def->label = L("Fan PWM from 0-100"); @@ -4241,6 +4260,17 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvancedE | comSuSi; def->set_default_value(new ConfigOptionString{ "" }); + def = this->add("fan_printer_min_speed", coInt); + def->label = L("Minimum fan speed"); + def->full_label = L("Minimum fan speed"); + def->category = OptionCategory::general; + def->tooltip = L("This setting represents the minimum fan speed (like minimum PWM) your fan needs to work."); + def->sidetext = L("%"); + def->min = 0; + def->max = 100; + def->mode = comSimpleAE | comSuSi; + def->set_default_value(new ConfigOptionInt(35)); + def = this->add("printer_model", coString); def->label = L("Printer type"); def->tooltip = L("Type of the printer."); @@ -6415,36 +6445,36 @@ void PrintConfigDef::init_fff_params() auto it_opt = options.find(opt_key); assert(it_opt != options.end()); def = this->add_nullable(std::string("filament_") + opt_key, it_opt->second.type); - def->label = it_opt->second.label; + def->label = it_opt->second.label; def->full_label = it_opt->second.full_label; - def->tooltip = it_opt->second.tooltip; + def->tooltip = it_opt->second.tooltip; def->sidetext = it_opt->second.sidetext; - def->mode = it_opt->second.mode; + def->mode = it_opt->second.mode; // create default value with the default value is taken from the default value of the config. // put a nil value as first entry. switch (def->type) { case coBools: { ConfigOptionBoolsNullable* opt = new ConfigOptionBoolsNullable(it_opt->second.default_value.get()->get_bool()); - opt->values.push_back(ConfigOptionBoolsNullable::NIL_VALUE()); + opt->set_at(ConfigOptionBoolsNullable::NIL_VALUE(), 0); def->set_default_value(opt); break; } case coFloats: { ConfigOptionFloatsNullable *opt = new ConfigOptionFloatsNullable(it_opt->second.default_value.get()->get_float()); - opt->values.push_back(ConfigOptionFloatsNullable::NIL_VALUE()); + opt->set_any(ConfigOptionFloatsNullable::create_nil(), 0); def->set_default_value(opt); break; } case coPercents: { ConfigOptionPercentsNullable *opt = new ConfigOptionPercentsNullable(it_opt->second.default_value.get()->get_float()); - opt->values.push_back(ConfigOptionPercentsNullable::NIL_VALUE()); + opt->set_any(ConfigOptionFloatsNullable::create_nil(), 0); def->set_default_value(opt); break; } case coFloatsOrPercents: { ConfigOptionFloatsOrPercentsNullable*opt = new ConfigOptionFloatsOrPercentsNullable( static_cast(it_opt->second.default_value.get())->get_at(0)); - opt->values.push_back(ConfigOptionFloatsOrPercentsNullable::NIL_VALUE()); + opt->set_at(ConfigOptionFloatsOrPercentsNullable::NIL_VALUE(), 0); def->set_default_value(opt); break; } @@ -7639,6 +7669,16 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va if (boost::starts_with(opt_key, "thin_perimeters") && value == "1") value = "100%"; + if ("fan_always_on" == opt_key) { + if (value != "1") { + //min_fan_speed is already converted to default_fan_speed, just has to deactivate it if not always_on + opt_key = "default_fan_speed"; // note: maybe this doesn't works, as default_fan_speed can also get its value from min_fan_speed + value = "0"; + } else { + opt_key = ""; + } + } + //prusa if ("gcode_flavor" == opt_key) { if ("reprap" == value) @@ -7711,6 +7751,11 @@ std::map PrintConfigDef::from_prusa(t_config_option_key value = "rectilinear"; output["fill_angle_increment"] = "90"; } + if ("fan_always_on" == opt_key) { + //min_fan_speed is already converted to default_fan_speed, just has to deactivate it if not always_on + if (value != "1") + output["default_fan_speed"] = "0"; + } return output; } @@ -7782,6 +7827,7 @@ std::unordered_set prusa_export_to_remove_keys = { "curve_smoothing_angle_convex", "curve_smoothing_cutoff_dist", "curve_smoothing_precision", +//"default_fan_speed", used to convert to min_fan_speed & fan_always_on "default_speed", "enforce_full_fill_volume", "exact_last_layer_height", @@ -7801,6 +7847,7 @@ std::unordered_set prusa_export_to_remove_keys = { "extrusion_spacing", "fan_kickstart", "fan_percentage", +"fan_printer_min_speed", "fan_speedup_overhangs", "fan_speedup_time", "feature_gcode", @@ -8119,6 +8166,16 @@ std::map PrintConfigDef::to_prusa(t_config_option_key& if ("bed_custom_texture" == opt_key || "Bed custom texture" == opt_key) { value = Slic3r::find_full_path(value, value).generic_string(); } + if ("default_fan_speed" == opt_key) { + if (value == "0") { + opt_key = "min_fan_speed"; + value = all_conf.option("fan_printer_min_speed")->get_float(); + new_entries["fan_always_on"] = "0"; + } else { + opt_key = "min_fan_speed"; + new_entries["fan_always_on"] = "1"; + } + } return new_entries; } diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 896e210361c..2fd8d4d6150 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1002,8 +1002,9 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloats, extruder_temperature_offset)) ((ConfigOptionString, extrusion_axis)) ((ConfigOptionFloats, extrusion_multiplier)) - ((ConfigOptionBool, fan_percentage)) ((ConfigOptionFloat, fan_kickstart)) + ((ConfigOptionBool, fan_percentage)) + ((ConfigOptionInt, fan_printer_min_speed)) ((ConfigOptionBool, fan_speedup_overhangs)) ((ConfigOptionFloat, fan_speedup_time)) ((ConfigOptionFloats, filament_cost)) @@ -1050,7 +1051,8 @@ PRINT_CONFIG_CLASS_DEFINE( // r - regular expression // i - case insensitive // w - whole word - ((ConfigOptionStrings, gcode_substitutions)) ((ConfigOptionString, layer_gcode)) + ((ConfigOptionStrings, gcode_substitutions)) + ((ConfigOptionString, layer_gcode)) ((ConfigOptionString, feature_gcode)) ((ConfigOptionFloat, max_gcode_per_second)) ((ConfigOptionFloatOrPercent, max_print_speed)) @@ -1148,6 +1150,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( //((ConfigOptionBools, cooling)) ((ConfigOptionFloatOrPercent, default_acceleration)) ((ConfigOptionInts, disable_fan_first_layers)) + ((ConfigOptionInts, default_fan_speed)) ((ConfigOptionEnum, draft_shield)) ((ConfigOptionFloat, duplicate_distance)) ((ConfigOptionBool, enforce_retract_first_layer)) @@ -1157,7 +1160,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionFloat, extruder_clearance_radius)) ((ConfigOptionStrings, extruder_colour)) ((ConfigOptionPoints, extruder_offset)) - ((ConfigOptionBools, fan_always_on)) + //((ConfigOptionBools, fan_always_on)) ((ConfigOptionFloats, fan_below_layer_time)) ((ConfigOptionStrings, filament_colour)) ((ConfigOptionStrings, filament_custom_variables)) @@ -1186,7 +1189,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionStrings, milling_toolchange_start_gcode)) //((ConfigOptionPoints, milling_offset)) //((ConfigOptionFloats, milling_z_offset)) - ((ConfigOptionInts, min_fan_speed)) + //((ConfigOptionInts, min_fan_speed)) // now fan_printer_min_speed ((ConfigOptionFloatsOrPercents, min_layer_height)) ((ConfigOptionFloats, min_print_speed)) ((ConfigOptionFloat, min_skirt_length)) diff --git a/src/slic3r/GUI/PresetHints.cpp b/src/slic3r/GUI/PresetHints.cpp index 81963a1a5a7..cb549477076 100644 --- a/src/slic3r/GUI/PresetHints.cpp +++ b/src/slic3r/GUI/PresetHints.cpp @@ -14,113 +14,185 @@ namespace Slic3r { +using Slic3r::GUI::format_wxstr; + +void format_simple_fan_speed(wxString &out, int min_speed, int default_speed, wxString &&feature_name, int fan_speed) { + if (fan_speed > 0) + fan_speed = std::max(fan_speed, min_speed); + if (fan_speed >= 0 && fan_speed != default_speed) { + if (fan_speed == 0) { + out += "\n" + format_wxstr(_L("Over %1% it will be off."), feature_name); + } else { + out += "\n" + format_wxstr(_L("Over %1% it will be at %2%%%."), feature_name, fan_speed); + } + } +} +void format_double_fan_speed(wxString& out, int min_speed, int default_speed, wxString&& feature_name_1, int fan_speed_1, wxString&& feature_name_2, int fan_speed_2) { + if (fan_speed_1 > 0) + fan_speed_1 = std::max(fan_speed_1, min_speed); + if (fan_speed_2 > 0) + fan_speed_2 = std::max(fan_speed_2, min_speed); + if (fan_speed_1 >= 0 && fan_speed_1 != default_speed) { + if (fan_speed_1 == fan_speed_2 || fan_speed_2 < 0) { + if (fan_speed_1 == 0) + out += "\n" + format_wxstr(_L("Over %1% and %2% it will be off."), feature_name_1, feature_name_2); + else + out += "\n" + format_wxstr(_L("Over %1% and %2% it will be fixed to %3%%%."), feature_name_1, feature_name_2, fan_speed_1); + } else if (fan_speed_2 == default_speed) { + format_simple_fan_speed(out, min_speed, default_speed, std::move(feature_name_1), fan_speed_1); + } else { + if (fan_speed_1 == 0) + out += "\n" + format_wxstr(_L("Over %1% it will be off, and over %2% fixed to %3%%%."), feature_name_1, feature_name_2, fan_speed_2); + else if (fan_speed_2 == 0) + out += "\n" + format_wxstr(_L("Over %1% it will be fixed to %2%%%, and off over %3%."), feature_name_1, fan_speed_1, feature_name_2); + else + out += "\n" + format_wxstr(_L("Over %1% it will be fixed to %2%%%, and over %3% to %4%%%."), feature_name_1, fan_speed_1, feature_name_2, fan_speed_2); + } + } else if (fan_speed_2 >= 0 && fan_speed_2 != default_speed) { + format_simple_fan_speed(out, min_speed, default_speed, std::move(feature_name_2), fan_speed_2); + } +} + +void format_simple_fan_min_speed(wxString& out, int min_speed, int default_speed, wxString&& feature_name, int fan_speed) { + if (fan_speed > 0) + fan_speed = std::max(fan_speed, min_speed); + if (fan_speed >= 0 && fan_speed != default_speed) { + if (fan_speed == 0) + out += "\n" + format_wxstr(_L("Over %1% it will be off."), feature_name); + else + out += "\n" + format_wxstr(_L("Over %1% it will be at least %2%%%."), feature_name, fan_speed); + } +} +void format_double_fan_min_speed(wxString& out, int min_speed, int default_speed, wxString&& feature_name_1, int fan_speed_1, wxString&& feature_name_2, int fan_speed_2) { + if (fan_speed_1 > 0) + fan_speed_1 = std::max(fan_speed_1, min_speed); + if (fan_speed_2 > 0) + fan_speed_2 = std::max(fan_speed_2, min_speed); + if (fan_speed_1 >= 0 && fan_speed_1 != default_speed) { + if (fan_speed_1 == fan_speed_2 || fan_speed_2 < 0) { + if (fan_speed_1 == 0) + out += "\n" + format_wxstr(_L("Over %1% and %2% it will be off."), feature_name_1, feature_name_2); + else + out += "\n" + format_wxstr(_L("Over %1% and %2% it will be at least %3%%%."), feature_name_1, feature_name_2, fan_speed_1); + } + else if (fan_speed_2 == default_speed) { + format_simple_fan_speed(out, min_speed, default_speed, std::move(feature_name_1), fan_speed_1); + } + else { + if (fan_speed_1 == 0) + out += "\n" + format_wxstr(_L("Over %1% it will be off, and over %2% at least %3%%%."), feature_name_1, feature_name_2, fan_speed_2); + else if (fan_speed_2 == 0) + out += "\n" + format_wxstr(_L("Over %1% it will be at least %2%%%, and off over %3%."), feature_name_1, fan_speed_1, feature_name_2); + else + out += "\n" + format_wxstr(_L("Over %1% it will be at least %2%%%, and over %3% at least %4%%%."), feature_name_1, fan_speed_1, feature_name_2, fan_speed_2); + } + } + else if (fan_speed_2 >= 0 && fan_speed_2 != default_speed) { + format_simple_fan_speed(out, min_speed, default_speed, std::move(feature_name_2), fan_speed_2); + } +} + #define MIN_BUF_LENGTH 4096 -std::string PresetHints::cooling_description(const Preset &preset) +std::string PresetHints::cooling_description(const Preset &preset_fil, const Preset& preset_printer) { - std::string out; - int min_fan_speed = preset.config.opt_int("min_fan_speed", 0); - int max_fan_speed = preset.config.opt_int("max_fan_speed", 0); - int top_fan_speed = preset.config.opt_int("top_fan_speed", 0); - int supp_inter_fan_speed = preset.config.opt_int("support_material_interface_fan_speed", 0); - int bridge_fan_speed = preset.config.opt_int("bridge_fan_speed", 0); - int bridge_internal_fan_speed = preset.config.opt_int("bridge_internal_fan_speed", 0); - int ext_peri_fan_speed = preset.config.opt_int("external_perimeter_fan_speed", 0); - int disable_fan_first_layers = preset.config.opt_int("disable_fan_first_layers", 0); - int full_fan_speed_layer = preset.config.opt_int("full_fan_speed_layer", 0); - float slowdown_below_layer_time = preset.config.opt_float("slowdown_below_layer_time", 0); - int min_print_speed = int(preset.config.opt_float("min_print_speed", 0) + 0.5); - int max_speed_reduc = int(preset.config.opt_float("max_speed_reduction", 0)); - float fan_below_layer_time = preset.config.opt_float("fan_below_layer_time", 0); - - //for the time being, -1 shoudl eb for disable, but it's 0 from legacy. - if (top_fan_speed == 0) top_fan_speed = -1; - if (bridge_fan_speed == 0) bridge_fan_speed = -1; - if (bridge_internal_fan_speed == 0) bridge_internal_fan_speed = -1; - if (ext_peri_fan_speed == 0) ext_peri_fan_speed = -1; - if (top_fan_speed == 1) top_fan_speed = 0; - if (bridge_fan_speed == 1) bridge_fan_speed = 0; - if (bridge_internal_fan_speed == 1) bridge_internal_fan_speed = 0; - if (ext_peri_fan_speed == 1) ext_peri_fan_speed = 0; + wxString out; + // -1 is disable, 0 or 1 is "no fan". (and 1 will be "low fan" in the future) + const int min_fan_speed = preset_printer.config.get_int("fan_printer_min_speed"); + const int default_fan_speed = preset_fil.config.get_int("default_fan_speed"); + const int max_fan_speed = preset_fil.config.opt_int("max_fan_speed", 0); + const int peri_fan_speed = preset_fil.config.opt_int("perimeter_fan_speed", 0) == 1 ? 0 : preset_fil.config.get_int("perimeter_fan_speed"); + const int ext_peri_fan_speed = preset_fil.config.opt_int("external_perimeter_fan_speed", 0) == 1 ? 0 : preset_fil.config.get_int("external_perimeter_fan_speed"); + const int infill_fan_speed = preset_fil.config.opt_int("infill_fan_speed", 0) == 1 ? 0 : preset_fil.config.get_int("infill_fan_speed"); + const int solid_fan_speed = preset_fil.config.opt_int("solid_infill_fan_speed", 0) == 1 ? 0 : preset_fil.config.get_int("solid_infill_fan_speed"); + const int top_fan_speed = preset_fil.config.opt_int("top_fan_speed", 0) == 1 ? 0 : preset_fil.config.get_int("top_fan_speed"); + const int support_fan_speed = preset_fil.config.opt_int("support_material_fan_speed", 0) == 1 ? 0 : preset_fil.config.get_int("support_material_fan_speed"); + const int supp_inter_fan_speed = preset_fil.config.opt_int("support_material_interface_fan_speed", 0) == 1 ? 0 : preset_fil.config.get_int("support_material_interface_fan_speed"); + const int bridge_fan_speed = preset_fil.config.opt_int("bridge_fan_speed", 0) == 1 ? 0 : preset_fil.config.get_int("bridge_fan_speed"); + const int bridge_internal_fan_speed = preset_fil.config.opt_int("bridge_internal_fan_speed", 0) == 1 ? 0 : preset_fil.config.get_int("bridge_internal_fan_speed"); + const int overhangs_fan_speed = preset_fil.config.opt_int("overhangs_fan_speed", 0) == 1 ? 0 : preset_fil.config.get_int("overhangs_fan_speed"); + const int gap_fill_fan_speed = preset_fil.config.opt_int("gap_fill_fan_speed", 0) == 1 ? 0 : preset_fil.config.get_int("gap_fill_fan_speed"); + const int disable_fan_first_layers = preset_fil.config.opt_int("disable_fan_first_layers", 0); + const int full_fan_speed_layer = preset_fil.config.opt_int("full_fan_speed_layer", 0); + const float slowdown_below_layer_time = preset_fil.config.opt_float("slowdown_below_layer_time", 0); + const int min_print_speed = int(preset_fil.config.opt_float("min_print_speed", 0) + 0.5); + const int max_speed_reduc = int(preset_fil.config.opt_float("max_speed_reduction", 0)); + const float fan_below_layer_time = preset_fil.config.opt_float("fan_below_layer_time", 0); //if (preset.config.opt_bool("cooling", 0)) { - out = _utf8(L("Fan")); - if (preset.config.opt_bool("fan_always_on", 0)) { - - out += " " + (boost::format(_utf8(L("will run at %1%%% by default"))) % min_fan_speed).str() ; - - if (ext_peri_fan_speed >= 0 && ext_peri_fan_speed != min_fan_speed) { - out += ", " + (boost::format(_utf8(L("at %1%%% over external perimeters"))) % ext_peri_fan_speed).str(); - } - if (top_fan_speed >= 0 && top_fan_speed != min_fan_speed) { - out += ", " + (boost::format(_utf8(L("at %1%%% over top fill surfaces"))) % top_fan_speed).str(); + if (default_fan_speed < 0) + out += _L("By default, there won't be any fan speed command."); + else if (default_fan_speed == 0) + out += _L("Fan will be turned off by default."); + else + out += format_wxstr(_L("Fan will run at %1%%% by default."), default_fan_speed); + + format_double_fan_min_speed(out, min_fan_speed, default_fan_speed, _L("Internal perimeters"), peri_fan_speed, _L("External perimeters"), ext_peri_fan_speed); + format_simple_fan_min_speed(out, min_fan_speed, default_fan_speed, _L("Sparse infill"), infill_fan_speed); + format_simple_fan_min_speed(out, min_fan_speed, default_fan_speed, _L("Solid surfaces"), solid_fan_speed); + format_simple_fan_speed(out, min_fan_speed, default_fan_speed, _L("Top surfaces"), top_fan_speed); + format_double_fan_min_speed(out, min_fan_speed, default_fan_speed, _L("Supports"), support_fan_speed, _L("Support interfaces"), supp_inter_fan_speed); + format_double_fan_speed(out, min_fan_speed, default_fan_speed, _L("Bridges"), bridge_fan_speed, _L("Internal bridges"), bridge_internal_fan_speed); + format_simple_fan_min_speed(out, min_fan_speed, default_fan_speed, _L("Perimeter overhangs"), overhangs_fan_speed); + format_simple_fan_min_speed(out, min_fan_speed, default_fan_speed, _L("Gap fills"), gap_fill_fan_speed); + + bool has_disable = false; + if (disable_fan_first_layers > 1) { + out += "\n"; + out += format_wxstr(_L("Except for the first %1% layers where the fan is disabled"), disable_fan_first_layers); + has_disable = true; + } + else if (disable_fan_first_layers == 1) { + out += "\n"; + out += _L("Except for the first layer where the fan is disabled"); + has_disable = true; + } + if (full_fan_speed_layer > disable_fan_first_layers + 1 && disable_fan_first_layers > 0) { + out += " "; + out += format_wxstr(_L("and will gradually speed-up to the above speeds over %1% layers"), full_fan_speed_layer - disable_fan_first_layers); + has_disable = true; + } + if (full_fan_speed_layer > disable_fan_first_layers + 1 && disable_fan_first_layers > 0) { + out += " "; + wxString surface_list; + if (bridge_fan_speed > 0) { + surface_list += ","; + surface_list += _L("Bridges"); } - if (supp_inter_fan_speed >= 0 && supp_inter_fan_speed != min_fan_speed) { - out += ", " + (boost::format(_utf8(L("at %1%%% over support interface surfaces"))) % supp_inter_fan_speed).str(); + if (bridge_internal_fan_speed > 0) { + surface_list += ","; + surface_list += _L("Internal bridges"); } - if (bridge_fan_speed >= 0 && bridge_fan_speed > min_fan_speed) { - if (bridge_internal_fan_speed < 0) - out += ", " + (boost::format(_utf8(L("at %1%%% over all bridges"))) % bridge_fan_speed).str(); - else - out += ", " + (boost::format(_utf8(L("at %1%%% over bridges"))) % bridge_fan_speed).str(); + if (supp_inter_fan_speed > 0) { + surface_list += ","; + surface_list += _L("Support interfaces"); } - if (bridge_internal_fan_speed >= 0){ - if (bridge_internal_fan_speed > min_fan_speed) { - out += ", " + (boost::format(_utf8(L("at %1%%% over infill bridges"))) % bridge_internal_fan_speed).str(); - } else if (bridge_fan_speed >= 0 && bridge_fan_speed > min_fan_speed) { - out += ", " + (boost::format(_utf8(L("at %1%%% over infill bridges"))) % min_fan_speed).str(); - } + if (overhangs_fan_speed > 0) { + surface_list += ","; + surface_list += _L("Perimeter overhangs"); } - if (disable_fan_first_layers > 1) - out += ", " + (boost::format(_utf8(L("except for the first %1% layers where the fan is disabled"))) % disable_fan_first_layers).str(); - else if (disable_fan_first_layers == 1) - out += ", " + _utf8(L("except for the first layer where the fan is disabled")); - if(full_fan_speed_layer > disable_fan_first_layers + 1 && disable_fan_first_layers > 0) - out += (boost::format(_utf8(L(" and will gradually speed-up to the above speeds over %1% layers"))) % (full_fan_speed_layer - disable_fan_first_layers)).str(); + + out += format_wxstr(_L("but for %1% where the speed-up phase is skipped."), surface_list.substr(1)); + has_disable = true; + } + if(has_disable) out += "."; - } else - out += " " + _utf8(L("will be turned off by default.")); - if (fan_below_layer_time > 0 && fan_below_layer_time > slowdown_below_layer_time && max_fan_speed > min_fan_speed) { - out += (boost::format(_utf8(L("\n\nIf estimated layer time is below ~%1%s, but still greater than ~%2%s, " - "fan will run at a proportionally increasing speed between %3%%% and %4%%%"))) - % fan_below_layer_time % slowdown_below_layer_time % min_fan_speed % max_fan_speed).str(); - - if (ext_peri_fan_speed > max_fan_speed) { - out += ", " + (boost::format(_utf8(L("at %1%%% over external perimeters"))) % ext_peri_fan_speed).str(); - } else if (ext_peri_fan_speed > min_fan_speed) { - out += ", " + (boost::format(_utf8(L("between %1%%% %2%%% over external perimeters"))) % ext_peri_fan_speed % max_fan_speed).str(); - } - if (top_fan_speed >= 0) { - out += ", " + (boost::format(_utf8(L("at %1%%% over top fill surfaces"))) % top_fan_speed).str(); - } - if (supp_inter_fan_speed >= 0) { - out += ", " + (boost::format(_utf8(L("at %1%%% over support interface surfaces"))) % supp_inter_fan_speed).str(); - } - if (bridge_fan_speed > max_fan_speed) { - out += ", " + (boost::format(_utf8(L("at %1%%% over bridges"))) % bridge_fan_speed).str(); - } else if (bridge_fan_speed > min_fan_speed) { - out += ", " + (boost::format(_utf8(L("between %1%%% %2%%% over bridges"))) % bridge_fan_speed % max_fan_speed).str(); - } - if (bridge_internal_fan_speed > max_fan_speed) { - out += ", " + (boost::format(_utf8(L("at %1%%% over infill bridges"))) % bridge_internal_fan_speed).str(); - } else if (bridge_internal_fan_speed > min_fan_speed) { - out += ", " + (boost::format(_utf8(L("between %1%%% %2%%% over infill bridges"))) % bridge_internal_fan_speed % max_fan_speed).str(); - } - if (disable_fan_first_layers > 1) - out += " ; " + ((boost::format(_utf8(L("except for the first %1% layers where the fan is disabled"))) % disable_fan_first_layers).str()); - else if (disable_fan_first_layers == 1) - out += " ; "+ _utf8(L("except for the first layer where the fan is disabled")); - if (full_fan_speed_layer > disable_fan_first_layers + 1 && disable_fan_first_layers > 0) - out += (boost::format(_utf8(L(" and will gradually speed-up to the above speeds over %1% layers"))) % (full_fan_speed_layer - disable_fan_first_layers)).str(); - out += "."; + out += format_wxstr(_L("\n\nIf estimated layer time is below ~%1%s, but still greater than ~%2%s, " + "fan will run at a proportionally increasing speed between %3%%% and %4%%%"), + fan_below_layer_time, slowdown_below_layer_time, min_fan_speed, max_fan_speed); + out += ".\n"; + out += format_wxstr(_L("If the fan speed is set, it will proportionally increasing speed between this value and %1%%%."), max_fan_speed); + out += "\n"; + out += format_wxstr(_L("If the fan speed is set and is higher than %1%%%, it won't be changed."), max_fan_speed); + out += "\n"; + out += format_wxstr(_L("Also, the fan speed over %1% won't be touched by this feature."), format_wxstr("%1%, %2%, %3%, %4%", _L("Top surfaces"), _L("Ironings"), _L("Bridges"), _L("Internal bridges"))); } if (slowdown_below_layer_time > 0) { - out += (boost::format(_utf8(L("\n\nIf estimated layer time is below ~%1%s"))) % slowdown_below_layer_time).str(); if (max_fan_speed > 0 && max_fan_speed > min_fan_speed) { @@ -149,21 +221,24 @@ std::string PresetHints::cooling_description(const Preset &preset) % min_print_speed).str(); } - //tooltip for Depractaed values - bridge_fan_speed = preset.config.opt_int("bridge_fan_speed", 0); - bridge_internal_fan_speed = preset.config.opt_int("bridge_internal_fan_speed", 0); - ext_peri_fan_speed = preset.config.opt_int("external_perimeter_fan_speed", 0); - top_fan_speed = preset.config.opt_int("top_fan_speed", 0); - if (top_fan_speed == 0) - out += "\n\n!!! 0 for the Top fan speed is Deprecated, please set it to -1 to disable it !!!"; - if (ext_peri_fan_speed == 0) - out += "\n\n!!! 0 for the External perimeters fan speed is Deprecated, please set it to -1 to disable it !!!"; - if (bridge_fan_speed == 0) - out += "\n\n!!! 0 for the Bridge fan speed is Deprecated, please set it to -1 to disable it !!!"; - if (bridge_internal_fan_speed == 0) - out += "\n\n!!! 0 for the Infill bridge fan speed is Deprecated, please set it to -1 to disable it !!!"; + if (fan_below_layer_time > 0 || slowdown_below_layer_time > 0) { + out += "\n\n"; + out += _L("Note: The layer time for the cooling is currently computed with infinite acceleration, and so is very optimistic."); + } - return out; + //tooltip for Depractaed values + if (preset_fil.config.opt_int("top_fan_speed", 0) == 1) + out += "\n\n! 1 for the Top fan speed is Deprecated, please set it to 0 to stop the fan!"; + if (preset_fil.config.opt_int("top_fan_speed", 0) == 1) + out += "\n\n! 1 for the Top fan speed is Deprecated, please set it to 0 to stop the fan!"; + if (preset_fil.config.opt_int("external_perimeter_fan_speed", 0) == 1) + out += "\n\n! 1 for the External perimeters fan speed is Deprecated, please set it to 0 to stop the fan!"; + if (preset_fil.config.opt_int("bridge_fan_speed", 0) == 1) + out += "\n\n! 1 for the Bridge fan speed is Deprecated, please set it to 0 to stop the fan!"; + if (preset_fil.config.opt_int("bridge_internal_fan_speed", 0) == 1) + out += "\n\n! 1 for the Infill bridge fan speed is Deprecated, please set it to 0 to stop the fan!"; + + return out.ToStdString(); } static const ConfigOptionFloatOrPercent& first_positive(const ConfigOptionFloatOrPercent *v1, const ConfigOptionFloatOrPercent &v2, const ConfigOptionFloatOrPercent &v3) diff --git a/src/slic3r/GUI/PresetHints.hpp b/src/slic3r/GUI/PresetHints.hpp index cee5956a2f1..56926846eae 100644 --- a/src/slic3r/GUI/PresetHints.hpp +++ b/src/slic3r/GUI/PresetHints.hpp @@ -12,7 +12,7 @@ class PresetHints { public: // Produce a textual description of the cooling logic of a currently active filament. - static std::string cooling_description(const Preset &preset); + static std::string cooling_description(const Preset &preset_filament, const Preset& preset_printer); // Produce a textual description of the maximum flow achived for the current configuration // (the current printer, filament and print settigns). diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 4a07e187cb9..fe90ddb5368 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2944,7 +2944,7 @@ void TabFilament::update_description_lines() return; if (std::find(m_active_page->descriptions.begin(), m_active_page->descriptions.end(), "cooling") != m_active_page->descriptions.end() && m_cooling_description_line) - m_cooling_description_line->SetText(from_u8(PresetHints::cooling_description(m_presets->get_edited_preset()))); + m_cooling_description_line->SetText(from_u8(PresetHints::cooling_description(m_presets->get_edited_preset(), m_preset_bundle->printers.get_edited_preset()))); if (std::find(m_active_page->descriptions.begin(), m_active_page->descriptions.end(), "volumetric_speed") != m_active_page->descriptions.end() && m_volumetric_speed_description_line) this->update_volumetric_flow_preset_hints(); } @@ -2956,12 +2956,12 @@ void TabFilament::toggle_options() if ( std::find(m_active_page->descriptions.begin(), m_active_page->descriptions.end(), "cooling") != m_active_page->descriptions.end()) { - bool fan_always_on = m_config->opt_bool("fan_always_on", 0); + // bool fan_always_on = m_config->opt_bool("fan_always_on", 0); //get_field("max_fan_speed")->toggle(m_config->opt_float("fan_below_layer_time", 0) > 0); - Field* min_print_speed_field = get_field("min_print_speed"); - if (min_print_speed_field) - min_print_speed_field->toggle(m_config->opt_float("slowdown_below_layer_time", 0) > 0); + // Field* min_print_speed_field = get_field("min_print_speed"); + // if (min_print_speed_field) + // min_print_speed_field->toggle(m_config->opt_float("slowdown_below_layer_time", 0) > 0); // hidden 'cooling', it's now deactivated. //for (auto el : { "min_fan_speed", "disable_fan_first_layers" })