diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 355e6f763e..50c11640cb 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1829,6 +1829,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato m_max_layer_z = 0.f; m_last_width = 0.f; m_is_overhang_fan_on = false; + m_is_internal_bridge_fan_on = false; m_is_supp_interface_fan_on = false; #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_last_mm3_per_mm = 0.; @@ -5489,7 +5490,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, // { "75%", Overhang_threshold_4_4 }, // { "95%", Overhang_threshold_bridge } auto check_overhang_fan = [&overhang_fan_threshold](float overlap, ExtrusionRole role) { - if (is_bridge(role)) { + if (role == erBridgeInfill || role == erOverhangPerimeter) { // ORCA: Split out bridge infill to internal and external to apply separate fan settings return true; } switch (overhang_fan_threshold) { @@ -5582,7 +5583,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, int overhang_threshold = overhang_fan_threshold == Overhang_threshold_none ? Overhang_threshold_none : overhang_fan_threshold - 1; if ((overhang_fan_threshold == Overhang_threshold_none && is_external_perimeter(path.role())) || - (path.get_overhang_degree() > overhang_threshold || is_bridge(path.role()))) { + (path.get_overhang_degree() > overhang_threshold || + (path.role() == erBridgeInfill || path.role() == erOverhangPerimeter))) { // ORCA: Add support for separate internal bridge fan speed control if (!m_is_overhang_fan_on) { gcode += ";_OVERHANG_FAN_START\n"; m_is_overhang_fan_on = true; @@ -5593,6 +5595,17 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, gcode += ";_OVERHANG_FAN_END\n"; } } + if (path.role() == erInternalBridgeInfill) { // ORCA: Add support for separate internal bridge fan speed control + if (!m_is_internal_bridge_fan_on) { + gcode += ";_INTERNAL_BRIDGE_FAN_START\n"; + m_is_internal_bridge_fan_on = true; + } + } else { + if (m_is_internal_bridge_fan_on) { + m_is_internal_bridge_fan_on = false; + gcode += ";_INTERNAL_BRIDGE_FAN_END\n"; + } + } } if (supp_interface_fan_speed >= 0 && path.role() == erSupportMaterialInterface) { if (!m_is_supp_interface_fan_on) { @@ -5727,6 +5740,9 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, bool cur_fan_enabled = false; if( m_enable_cooling_markers && enable_overhang_bridge_fan) pre_fan_enabled = check_overhang_fan(new_points[0].overlap, path.role()); + + if(path.role() == erInternalBridgeInfill) // ORCA: Add support for separate internal bridge fan speed control + pre_fan_enabled = true; double path_length = 0.; for (size_t i = 1; i < new_points.size(); i++) { @@ -5750,6 +5766,19 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, } pre_fan_enabled = cur_fan_enabled; } + // ORCA: Add support for separate internal bridge fan speed control + if (path.role() == erInternalBridgeInfill) { + if (!m_is_internal_bridge_fan_on) { + gcode += ";_INTERNAL_BRIDGE_FAN_START\n"; + m_is_internal_bridge_fan_on = true; + } + } else { + if (m_is_internal_bridge_fan_on) { + gcode += ";_INTERNAL_BRIDGE_FAN_END\n"; + m_is_internal_bridge_fan_on = false; + } + } + if (supp_interface_fan_speed >= 0 && path.role() == erSupportMaterialInterface) { if (!m_is_supp_interface_fan_on) { gcode += ";_SUPP_INTERFACE_FAN_START\n"; diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index cb39342d94..8cee34edbd 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -515,6 +515,7 @@ private: std::string _encode_label_ids_to_base64(std::vector ids); // Orca bool m_is_overhang_fan_on; + bool m_is_internal_bridge_fan_on; // ORCA: Add support for separate internal bridge fan speed control bool m_is_supp_interface_fan_on; // Markers for the Pressure Equalizer to recognize the extrusion type. // The Pressure Equalizer removes the markers from the final G-code. diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp index c83d854ee4..194afe9b1b 100644 --- a/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/src/libslic3r/GCode/CoolingBuffer.cpp @@ -65,6 +65,9 @@ struct CoolingLine TYPE_FORCE_RESUME_FAN = 1 << 14, TYPE_SUPPORT_INTERFACE_FAN_START = 1 << 15, TYPE_SUPPORT_INTERFACE_FAN_END = 1 << 16, + // ORCA: Add support for separate internal bridge fan speed control + TYPE_INTERNAL_BRIDGE_FAN_START = 1 << 17, + TYPE_INTERNAL_BRIDGE_FAN_END = 1 << 18, }; CoolingLine(unsigned int type, size_t line_start, size_t line_end) : @@ -511,6 +514,10 @@ std::vector CoolingBuffer::parse_layer_gcode(const std:: line.type = CoolingLine::TYPE_OVERHANG_FAN_START; } else if (boost::starts_with(sline, ";_OVERHANG_FAN_END")) { line.type = CoolingLine::TYPE_OVERHANG_FAN_END; + } else if (boost::starts_with(sline, ";_INTERNAL_BRIDGE_FAN_START")) { // ORCA: Add support for separate internal bridge fan speed control + line.type = CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START; + } else if (boost::starts_with(sline, ";_INTERNAL_BRIDGE_FAN_END")) { // ORCA: Add support for separate internal bridge fan speed control + line.type = CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_END; } else if (boost::starts_with(sline, ";_SUPP_INTERFACE_FAN_START")) { line.type = CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START; } else if (boost::starts_with(sline, ";_SUPP_INTERFACE_FAN_END")) { @@ -705,9 +712,11 @@ std::string CoolingBuffer::apply_layer_cooldown( new_gcode.reserve(gcode.size() * 2); bool overhang_fan_control= false; int overhang_fan_speed = 0; + bool internal_bridge_fan_control= false; // ORCA: Add support for separate internal bridge fan speed control + int internal_bridge_fan_speed = 0; // ORCA: Add support for separate internal bridge fan speed control bool supp_interface_fan_control= false; int supp_interface_fan_speed = 0; - auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &overhang_fan_control, &overhang_fan_speed, &supp_interface_fan_control, &supp_interface_fan_speed](bool immediately_apply) { + auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &overhang_fan_control, &overhang_fan_speed, &internal_bridge_fan_control, &internal_bridge_fan_speed, &supp_interface_fan_control, &supp_interface_fan_speed](bool immediately_apply) { #define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder) float fan_min_speed = EXTRUDER_CONFIG(fan_min_speed); float fan_speed_new = EXTRUDER_CONFIG(reduce_fan_stop_start_freq) ? fan_min_speed : 0; @@ -749,15 +758,27 @@ std::string CoolingBuffer::apply_layer_cooldown( supp_interface_fan_speed = EXTRUDER_CONFIG(support_material_interface_fan_speed); supp_interface_fan_control = supp_interface_fan_speed >= 0; + overhang_fan_control = overhang_fan_speed > fan_speed_new; + + // ORCA: Add support for separate internal bridge fan speed control + internal_bridge_fan_speed = EXTRUDER_CONFIG(internal_bridge_fan_speed); + internal_bridge_fan_control = internal_bridge_fan_speed >=0; + + if( internal_bridge_fan_speed < 0 ) { // ORCA: Backwards compatibility setting for Orca internal bridge fan speed setting - if set at -1 (which is the default) use the overhang fan speed settings. + internal_bridge_fan_speed = overhang_fan_speed; + internal_bridge_fan_control = overhang_fan_control; + } #undef EXTRUDER_CONFIG - overhang_fan_control= overhang_fan_speed > fan_speed_new; + } else { - overhang_fan_control= false; + overhang_fan_control = false; overhang_fan_speed = 0; fan_speed_new = 0; additional_fan_speed_new = 0; - supp_interface_fan_control= false; + supp_interface_fan_control = false; supp_interface_fan_speed = 0; + internal_bridge_fan_control = false; // ORCA: Add support for separate internal bridge fan speed control + internal_bridge_fan_speed = 0; // ORCA: Add support for separate internal bridge fan speed control } if (fan_speed_new != m_fan_speed) { m_fan_speed = fan_speed_new; @@ -780,6 +801,7 @@ std::string CoolingBuffer::apply_layer_cooldown( // Orca: Reduce set fan commands by deferring the GCodeWriter::set_fan calls. Inspired by SuperSlicer // define fan_speed_change_requests and initialize it with all possible types fan speed change requests std::unordered_map fan_speed_change_requests = {{CoolingLine::TYPE_OVERHANG_FAN_START, false}, + {CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START, false}, // ORCA: Add support for separate internal bridge fan speed control {CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START, false}, {CoolingLine::TYPE_FORCE_RESUME_FAN, false}}; bool need_set_fan = false; @@ -809,6 +831,16 @@ std::string CoolingBuffer::apply_layer_cooldown( fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START] = false; } need_set_fan = true; + } else if (line->type & CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START) { // ORCA: Add support for separate internal bridge fan speed control + if (internal_bridge_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START]) { + need_set_fan = true; + fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START] = true; + } + } else if (line->type & CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_END) { // ORCA: Add support for separate internal bridge fan speed control + if (internal_bridge_fan_control && fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START]) { + fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START] = false; + } + need_set_fan = true; } else if (line->type & CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START) { if (supp_interface_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]) { fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START] = true; @@ -917,6 +949,9 @@ std::string CoolingBuffer::apply_layer_cooldown( if (fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START]){ new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, overhang_fan_speed); m_current_fan_speed = overhang_fan_speed; + } else if (fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START]){ // ORCA: Add support for separate internal bridge fan speed control + new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, internal_bridge_fan_speed); + m_current_fan_speed = internal_bridge_fan_speed; } else if (fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]){ new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, supp_interface_fan_speed); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 134538dde5..388ed27648 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -860,7 +860,7 @@ static std::vector s_Preset_filament_options { "filament_wipe_distance", "additional_cooling_fan_speed", "nozzle_temperature_range_low", "nozzle_temperature_range_high", //SoftFever - "enable_pressure_advance", "pressure_advance","adaptive_pressure_advance","adaptive_pressure_advance_model","adaptive_pressure_advance_overhangs", "adaptive_pressure_advance_bridges","chamber_temperature", "filament_shrink","filament_shrinkage_compensation_z", "support_material_interface_fan_speed", "filament_notes" /*,"filament_seam_gap"*/, + "enable_pressure_advance", "pressure_advance","adaptive_pressure_advance","adaptive_pressure_advance_model","adaptive_pressure_advance_overhangs", "adaptive_pressure_advance_bridges","chamber_temperature", "filament_shrink","filament_shrinkage_compensation_z", "support_material_interface_fan_speed","internal_bridge_fan_speed", "filament_notes" /*,"filament_seam_gap"*/, "filament_loading_speed", "filament_loading_speed_start", "filament_unloading_speed", "filament_unloading_speed_start", "filament_toolchange_delay", "filament_cooling_moves", "filament_stamping_loading_speed", "filament_stamping_distance", "filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 31f225cfa2..b3a9db6f3c 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -193,6 +193,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "gcode_label_objects", "exclude_object", "support_material_interface_fan_speed", + "internal_bridge_fan_speed", // ORCA: Add support for separate internal bridge fan speed control "single_extruder_multi_material_priming", "activate_air_filtration", "during_print_exhaust_fan_speed", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 8fb93e3024..ec70b4d5ae 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -908,15 +908,19 @@ void PrintConfigDef::init_fff_params() def = this->add("enable_overhang_bridge_fan", coBools); - def->label = L("Force cooling for overhang and bridge"); - def->tooltip = L("Enable this option to optimize part cooling fan speed for overhang and bridge to get better cooling"); + def->label = L("Force cooling for overhangs and bridges"); + def->tooltip = L("Enable this option to allow adjustment of the part cooling fan speed for specifically for overhangs, internal and external " + "bridges. Setting the fan speed specifically for these features can improve overall print quality and reduce warping."); def->mode = comSimple; def->set_default_value(new ConfigOptionBools{ true }); def = this->add("overhang_fan_speed", coInts); - def->label = L("Fan speed for overhang"); - def->tooltip = L("Force part cooling fan to be this speed when printing bridge or overhang wall which has large overhang degree. " - "Forcing cooling for overhang and bridge can get better quality for these part"); + def->label = L("Overhangs and external bridges fan speed"); + def->tooltip = L("Use this part cooling fan speed when printing bridges or overhang walls with an overhang threshold that exceeds " + "the value set in the 'Overhangs cooling threshold' parameter above. Increasing the cooling specifically for overhangs " + "and bridges can improve the overall print quality of these features.\n\n" + "Please note, this fan speed is clamped on the lower end by the minimum fan speed threshold set above. It is also adjusted " + "upwards up to the maximum fan speed threshold when the minimum layer time threshold is not met."); def->sidetext = L("%"); def->min = 0; def->max = 100; @@ -924,10 +928,10 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionInts { 100 }); def = this->add("overhang_fan_threshold", coEnums); - def->label = L("Cooling overhang threshold"); - def->tooltip = L("Force cooling fan to be specific speed when overhang degree of printed part exceeds this value. " - "Expressed as percentage which indicates how much width of the line without support from lower layer. " - "0% means forcing cooling for all outer wall no matter how much overhang degree"); + def->label = L("Overhang cooling activation threshold"); + def->tooltip = L("When the overhang exceeds this specified threshold, force the cooling fan to run at the 'Overhang Fan Speed' set below. " + "This threshold is expressed as a percentage, indicating the portion of each line's width that is unsupported by the layer " + "beneath it. Setting this value to 0% forces the cooling fan to run for all outer walls, regardless of the overhang degree."); def->sidetext = ""; def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); def->mode = comAdvanced; @@ -2586,15 +2590,27 @@ void PrintConfigDef::init_fff_params() def = this->add("support_material_interface_fan_speed", coInts); def->label = L("Support interface fan speed"); - def->tooltip = L("This fan speed is enforced during all support interfaces, to be able to weaken their bonding with a high fan speed." - "\nSet to -1 to disable this override." - "\nCan only be overridden by disable_fan_first_layers."); + def->tooltip = L("This part cooling fan speed is applied when printing support interfaces. Setting this parameter to a higher than regular speed " + " reduces the layer binding strength between supports and the supported part, making them easier to separate." + "\nSet to -1 to disable it." + "\nThis setting is overridden by disable_fan_first_layers."); def->sidetext = L("%"); def->min = -1; def->max = 100; def->mode = comAdvanced; def->set_default_value(new ConfigOptionInts{ -1 }); + // ORCA: Add support for separate internal bridge fan speed control + def = this->add("internal_bridge_fan_speed", coInts); + def->label = L("Internal bridges fan speed"); + def->tooltip = L("The part cooling fan speed used for all internal bridges. Set to -1 to use the overhang fan speed settings instead.\n\n" + "Reducing the internal bridges fan speed, compared to your regular fan speed, can help reduce part warping due to excessive " + "cooling applied over a large surface for a prolonged period of time."); + def->sidetext = L("%"); + def->min = -1; + def->max = 100; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionInts{ -1 }); def = this->add("fuzzy_skin", coEnum); def->label = L("Fuzzy Skin"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 33a0e7eabf..0f0f1640aa 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1331,6 +1331,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionBool, gcode_comments)) ((ConfigOptionInt, slow_down_layers)) ((ConfigOptionInts, support_material_interface_fan_speed)) + ((ConfigOptionInts, internal_bridge_fan_speed)) // ORCA: Add support for separate internal bridge fan speed control // Orca: notes for profiles from PrusaSlicer ((ConfigOptionStrings, filament_notes)) ((ConfigOptionString, notes)) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index fea8908d75..b111066620 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3445,6 +3445,7 @@ void TabFilament::build() optgroup->append_single_option_line("enable_overhang_bridge_fan", "auto-cooling"); optgroup->append_single_option_line("overhang_fan_threshold", "auto-cooling"); optgroup->append_single_option_line("overhang_fan_speed", "auto-cooling"); + optgroup->append_single_option_line("internal_bridge_fan_speed"); // ORCA: Add support for separate internal bridge fan speed control optgroup->append_single_option_line("support_material_interface_fan_speed"); optgroup = page->new_optgroup(L("Auxiliary part cooling fan"), L"param_cooling_aux_fan"); @@ -3605,7 +3606,7 @@ void TabFilament::toggle_options() auto cfg = m_preset_bundle->printers.get_edited_preset().config; if (m_active_page->title() == L("Cooling")) { bool has_enable_overhang_bridge_fan = m_config->opt_bool("enable_overhang_bridge_fan", 0); - for (auto el : {"overhang_fan_speed", "overhang_fan_threshold"}) + for (auto el : {"overhang_fan_speed", "overhang_fan_threshold", "internal_bridge_fan_speed"}) // ORCA: Add support for separate internal bridge fan speed control toggle_option(el, has_enable_overhang_bridge_fan); toggle_option("additional_cooling_fan_speed", cfg.opt_bool("auxiliary_fan"));