diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 180312aa6d..e8348b3bd5 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -96,12 +96,21 @@ inline bool is_solid_infill(ExtrusionRole role) || role == erIroning; } -inline bool is_bridge(ExtrusionRole role) { +inline bool is_bridge(ExtrusionRole role) +{ return role == erBridgeInfill || role == erInternalBridgeInfill || role == erOverhangPerimeter; } +// Orca +inline bool is_support(ExtrusionRole role) +{ + return role == erSupportMaterial + || role == erSupportMaterialInterface + || role == erSupportTransition; +} + class ExtrusionEntity { public: diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 80b9cb47ee..6740b2d234 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -5925,8 +5925,8 @@ std::string GCode::extrude_loop(const ExtrusionLoop& loop_ref, const auto speed_for_path = [&speed, &small_peri_speed](const ExtrusionPath& path) { // don't apply small perimeter setting for overhangs/bridges/non-perimeters - const bool is_small_peri = is_perimeter(path.role()) && !is_bridge(path.role()) && small_peri_speed > 0; - return is_small_peri ? small_peri_speed : speed; + const bool is_small_small_perimeter = small_peri_speed > 0 && !is_bridge(path.role()) && is_perimeter(path.role()); + return is_small_small_perimeter ? small_peri_speed : speed; }; @@ -5948,8 +5948,8 @@ std::string GCode::extrude_loop(const ExtrusionLoop& loop_ref, // Orca: end of multipath average mm3_per_mm value calculation if (!enable_seam_slope) { - for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) { - gcode += this->_extrude(*path, description, speed_for_path(*path)); + for (const ExtrusionPath& path : paths) { + gcode += this->_extrude(path, description, speed_for_path(path)); // Orca: Adaptive PA - dont adapt PA after the first multipath extrusion is completed // as we have already set the PA value to the average flow over the totality of the path // in the first extrude move @@ -5985,8 +5985,8 @@ std::string GCode::extrude_loop(const ExtrusionLoop& loop_ref, new_loop.clip_slope(seam_gap); // Then extrude it - for (const auto& p : new_loop.get_all_paths()) { - gcode += this->_extrude(*p, description, speed_for_path(*p)); + for (const ExtrusionPath* path : new_loop.get_all_paths()) { + gcode += this->_extrude(*path, description, speed_for_path(*path)); // Orca: Adaptive PA - dont adapt PA after the first pultipath extrusion is completed // as we have already set the PA value to the average flow over the totality of the path // in the first extrude move @@ -6142,7 +6142,7 @@ std::string GCode::extrude_path(const ExtrusionPath& path, const std::string& de std::string gcode = this->_extrude(path, description, speed); if (m_wipe.enable && FILAMENT_CONFIG(wipe)) { m_wipe.path = path.polyline.to_polyline(); - if (is_tree(this->config().support_type) && (path.role() == erSupportMaterial || path.role() == erSupportMaterialInterface || path.role() == erSupportTransition)) { + if (is_tree(this->config().support_type) && is_support(path.role())) { if ((m_wipe.path.first_point() - m_wipe.path.last_point()).cast().norm() > scale_(0.2)) { double min_dist = scale_(0.2); int i = 0; @@ -6210,13 +6210,30 @@ std::string GCode::extrude_infill(const Print &print, const std::vector SMALL_PERIMETER_LENGTH(NOZZLE_CONFIG(small_support_perimeter_threshold))) + return default_speed; + + double small_perimeter_speed = -1.0; + + const auto base_speed = (role == erSupportMaterialInterface) + ? NOZZLE_CONFIG(support_interface_speed) : NOZZLE_CONFIG(support_speed); + + if (NOZZLE_CONFIG(small_support_perimeter_speed).value == 0) + small_perimeter_speed = base_speed * 0.5; + else + small_perimeter_speed = NOZZLE_CONFIG(small_support_perimeter_speed).get_abs_value(base_speed); + + return small_perimeter_speed > 0 ? small_perimeter_speed : default_speed; + }; + std::string gcode; - if (! support_fills.entities.empty()) { + if (!support_fills.entities.empty()) { ExtrusionEntitiesPtr extrusions; extrusions.reserve(support_fills.entities.size()); @@ -6233,28 +6250,27 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill if (!support_fills.no_sort) chain_and_reorder_extrusion_entities(extrusions, m_last_pos.to_point()); - //const double support_speed = m_config.support_speed.value; - //const double support_interface_speed = m_config.get_abs_value("support_interface_speed"); for (const ExtrusionEntity *ee : extrusions) { ExtrusionRole role = ee->role(); - assert(role == erSupportMaterial || role == erSupportMaterialInterface || role == erSupportTransition || role == erIroning); + assert(is_support(role) || role == erIroning); + const char* label = (role == erSupportMaterial) ? support_label : ((role == erSupportMaterialInterface) ? support_interface_label : ((role == erIroning) ? support_ironing_label : support_transition_label)); - // BBS - //const double speed = (role == erSupportMaterial) ? support_speed : support_interface_speed; - const double speed = -1.0; + const ExtrusionPath* path = dynamic_cast(ee); const ExtrusionMultiPath* multipath = dynamic_cast(ee); const ExtrusionLoop* loop = dynamic_cast(ee); const ExtrusionEntityCollection* collection = dynamic_cast(ee); - if (path) - gcode += this->extrude_path(*path, label, speed); + + if (path) { + gcode += extrude_path(*path, label, speed_for_path(path->length(), role)); + } else if (multipath) { - gcode += this->extrude_multi_path(*multipath, label, speed); + gcode += extrude_multi_path(*multipath, label, speed_for_path(multipath->length(), role)); } else if (loop) { - gcode += this->extrude_loop(*loop, label, speed); + gcode += extrude_loop(*loop, label, speed_for_path(loop->length(), role)); } else if (collection) { gcode += extrude_support(*collection, support_extrusion_role); @@ -6574,12 +6590,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, speed = NOZZLE_CONFIG(initial_layer_infill_speed); } else if (path.role() == erGapFill) { speed = NOZZLE_CONFIG(gap_infill_speed); - } - else if (path.role() == erSupportMaterial || - path.role() == erSupportMaterialInterface) { - const double support_speed = NOZZLE_CONFIG(support_speed); - const double support_interface_speed = NOZZLE_CONFIG(support_interface_speed); - speed = (path.role() == erSupportMaterial) ? support_speed : support_interface_speed; + } else if (path.role() == erSupportMaterial) { + speed = NOZZLE_CONFIG(support_speed); + } else if (path.role() == erSupportMaterialInterface) { + speed = NOZZLE_CONFIG(support_interface_speed); } else { throw Slic3r::InvalidArgument("Invalid speed"); } diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index 18b0af9989..b3a145bed0 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -149,6 +149,7 @@ bool Layer::is_perimeter_compatible(const Print& print, const PrintRegion& a, co && config.inner_wall_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) == other_config.inner_wall_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) && config.outer_wall_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) == other_config.outer_wall_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) && config.small_perimeter_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) == other_config.small_perimeter_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) + && config.small_support_perimeter_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) == other_config.small_support_perimeter_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) && config.gap_infill_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) == other_config.gap_infill_speed.get_at(print.get_extruder_id(config.outer_wall_filament_id)) && config.filter_out_gap_fill.value == other_config.filter_out_gap_fill.value && config.detect_overhang_wall == other_config.detect_overhang_wall diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 233c259424..1177a5227d 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -3226,6 +3226,7 @@ double Model::findMaxSpeed(const ModelObject* object) { double topSolidInfillSpeedObj = Model::printSpeedMap.topSolidInfillSpeed; double supportSpeedObj = Model::printSpeedMap.supportSpeed; double smallPerimeterSpeedObj = Model::printSpeedMap.smallPerimeterSpeed; + double smallSupportPerimeterSpeedObj = Model::printSpeedMap.smallSupportPerimeterSpeed; for (std::string objectKey : objectKeys) { if (objectKey == "inner_wall_speed"){ perimeterSpeedObj = object->config.get().opt_float_nullable(objectKey, 0); @@ -3243,8 +3244,10 @@ double Model::findMaxSpeed(const ModelObject* object) { externalPerimeterSpeedObj = object->config.get().opt_float_nullable(objectKey, 0); if (objectKey == "small_perimeter_speed") smallPerimeterSpeedObj = object->config.get().opt_float_nullable(objectKey, 0); + if (objectKey == "small_support_perimeter_speed") + smallSupportPerimeterSpeedObj = object->config.get().opt_float_nullable(objectKey, 0); } - objMaxSpeed = std::max(perimeterSpeedObj, std::max(externalPerimeterSpeedObj, std::max(infillSpeedObj, std::max(solidInfillSpeedObj, std::max(topSolidInfillSpeedObj, std::max(supportSpeedObj, std::max(smallPerimeterSpeedObj, objMaxSpeed))))))); + objMaxSpeed = std::max(perimeterSpeedObj, std::max(externalPerimeterSpeedObj, std::max(infillSpeedObj, std::max(solidInfillSpeedObj, std::max(topSolidInfillSpeedObj, std::max(supportSpeedObj, std::max(smallPerimeterSpeedObj, std::max(smallSupportPerimeterSpeedObj, objMaxSpeed)))))))); if (objMaxSpeed <= 0) objMaxSpeed = 250.; return objMaxSpeed; } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index d04a6095c7..b15124d9ed 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -1467,6 +1467,7 @@ struct GlobalSpeedMap double topSolidInfillSpeed; double supportSpeed; double smallPerimeterSpeed; + double smallSupportPerimeterSpeed; double maxSpeed; Polygon bed_poly; }; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 20b60b389d..bbdcf52d25 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -1200,6 +1200,8 @@ static std::vector s_Preset_print_options{ "wall_maximum_deviation", "small_perimeter_speed", "small_perimeter_threshold", + "small_support_perimeter_speed", + "small_support_perimeter_threshold", "bridge_angle", "internal_bridge_angle", "relative_bridge_angle", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 5600785f59..c83d065809 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2191,6 +2191,28 @@ void PrintConfigDef::init_fff_params() def->nullable = true; def->set_default_value(new ConfigOptionFloatsNullable{0}); + def = this->add("small_support_perimeter_speed", coFloatsOrPercents); + def->label = L("Small support perimeters"); + def->category = L("Speed"); + def->tooltip = L("Same as \"Small perimeters\", but for supports. " + "This separate setting will affect the speed of support for areas <= `small_support_perimeter_threshold`. " + "If expressed as a percentage (for example: 80%), it will be calculated on the support or support interface speed setting above. " + "Set to zero for auto."); + def->sidetext = L("mm/s or %"); + def->ratio_over = "outer_wall_speed"; + def->min = 1; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatsOrPercentsNullable{FloatOrPercent(50, true)}); + + def = this->add("small_support_perimeter_threshold", coFloats); + def->label = L("Small support perimeters threshold"); + def->category = L("Speed"); + def->tooltip = L("This sets the threshold for small support perimeter length. The default threshold is 0mm."); + def->sidetext = L("mm"); // millimeters, CIS languages need translation + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatsNullable{0}); + def = this->add("wall_sequence", coEnum); def->label = L("Walls printing order"); def->category = L("Quality"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 7117e3101d..619d8f5c78 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1211,6 +1211,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, filter_out_gap_fill)) ((ConfigOptionFloatsOrPercentsNullable, small_perimeter_speed)) ((ConfigOptionFloatsNullable, small_perimeter_threshold)) + ((ConfigOptionFloatsOrPercentsNullable, small_support_perimeter_speed)) + ((ConfigOptionFloatsNullable, small_support_perimeter_threshold)) ((ConfigOptionFloat, top_solid_infill_flow_ratio)) ((ConfigOptionFloat, bottom_solid_infill_flow_ratio)) ((ConfigOptionFloatOrPercent, infill_anchor)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 912a68be95..c1caa3b0d9 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1111,6 +1111,8 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "outer_wall_speed" || opt_key == "small_perimeter_speed" || opt_key == "small_perimeter_threshold" + || opt_key == "small_support_perimeter_speed" + || opt_key == "small_support_perimeter_threshold" || opt_key == "sparse_infill_speed" || opt_key == "inner_wall_speed" || opt_key == "support_speed" @@ -1426,6 +1428,8 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "outer_wall_speed" || opt_key == "small_perimeter_speed" || opt_key == "small_perimeter_threshold" + || opt_key == "small_support_perimeter_speed" + || opt_key == "small_support_perimeter_threshold" || opt_key == "sparse_infill_speed" || opt_key == "inner_wall_speed" || opt_key == "internal_solid_infill_speed" diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 15da90b546..006b2a009f 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -846,6 +846,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in // toggle_line("support_speed", have_support_material || have_skirt_height); // toggle_line("support_interface_speed", have_support_material && have_support_interface); + // Orca: + for (auto el : {"small_support_perimeter_speed", "small_support_perimeter_threshold"}) + toggle_field(el, config->opt_bool("enable_support")); + // BBS //toggle_field("support_material_synchronize_layers", have_support_soluble); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index d56247e2ea..aea72d601f 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2809,6 +2809,8 @@ void TabPrint::build() optgroup->append_single_option_line("ironing_speed", "speed_settings_other_layers_speed#ironing-speed"); optgroup->append_single_option_line("support_speed", "speed_settings_other_layers_speed#support", 0); optgroup->append_single_option_line("support_interface_speed", "speed_settings_other_layers_speed#support-interface", 0); + optgroup->append_single_option_line("small_support_perimeter_speed", "speed_settings_other_layers_speed#small-tree-support-perimeters", 0); + optgroup->append_single_option_line("small_support_perimeter_threshold", "speed_settings_other_layers_speed#small-tree-support-perimeters-threshold", 0); optgroup = page->new_optgroup(L("Overhang speed"), L"param_overhang_speed", 15); optgroup->append_single_option_line("enable_overhang_speed", "speed_settings_overhang_speed#slow-down-for-overhang", 0);