From 014e9bbd042edea470cc7eb45ee683f3af71520f Mon Sep 17 00:00:00 2001 From: vovodroid Date: Sat, 20 Jul 2024 18:31:34 +0300 Subject: [PATCH 1/2] Remove "auto" wall direction --- src/libslic3r/GCode.cpp | 7 ++++-- src/libslic3r/PerimeterGenerator.cpp | 32 ++++++++++++++------------- src/libslic3r/PrintConfig.cpp | 8 +++---- src/libslic3r/PrintConfig.hpp | 1 - src/slic3r/GUI/ConfigManipulation.cpp | 7 +----- src/slic3r/GUI/PartPlate.cpp | 1 - 6 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index a5af72f4c9..37993966f0 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -5370,7 +5370,10 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou if (m_config.spiral_mode && !is_hole) { // if spiral vase, we have to ensure that all contour are in the same orientation. - loop.make_counter_clockwise(); + if (m_config.wall_direction == WallDirection::CounterClockwise) + loop.make_counter_clockwise(); + else + loop.make_clockwise(); } //if (loop.loop_role() == elrSkirt && (this->m_layer->id() % 2 == 1)) // loop.reverse(); @@ -5432,7 +5435,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou // 1 - the currently printed external perimeter and 2 - the neighbouring internal perimeter. if (m_config.wipe_before_external_loop.value && !paths.empty() && paths.front().size() > 1 && paths.back().size() > 1 && paths.front().role() == erExternalPerimeter && region_perimeters.size() > 1) { const bool is_full_loop_ccw = loop.polygon().is_counter_clockwise(); - bool is_hole_loop = (loop.loop_role() & ExtrusionLoopRole::elrHole) != 0; // loop.make_counter_clockwise(); + bool is_hole_loop = (loop.loop_role() & ExtrusionLoopRole::elrHole) != 0; const double nozzle_diam = nozzle_diameter; // note: previous & next are inverted to extrude "in the opposite direction, and we are "rewinding" diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index cc055c9d8a..7da2f20725 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -253,7 +253,10 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime ExtrusionLoop *eloop = static_cast(coll.entities[idx.first]); coll.entities[idx.first] = nullptr; - eloop->make_counter_clockwise(); + if (perimeter_generator.config->wall_direction == WallDirection::CounterClockwise) + eloop->make_counter_clockwise(); + else + eloop->make_clockwise(); eloop->inset_idx = loop.depth; if (loop.is_contour) { out.append(std::move(children.entities)); @@ -511,7 +514,10 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p if (!paths.empty()) { if (extrusion->is_closed) { ExtrusionLoop extrusion_loop(std::move(paths), pg_extrusion.is_contour ? elrDefault : elrHole); - extrusion_loop.make_counter_clockwise(); + if (perimeter_generator.config->wall_direction == WallDirection::CounterClockwise) + extrusion_loop.make_counter_clockwise(); + else + extrusion_loop.make_clockwise(); // TODO: it seems in practice that ExtrusionLoops occasionally have significantly disconnected paths, // triggering the asserts below. Is this a problem? for (auto it = std::next(extrusion_loop.paths.begin()); it != extrusion_loop.paths.end(); ++it) { @@ -1106,7 +1112,7 @@ static void reorient_perimeters(ExtrusionEntityCollection &entities, bool steep_ } if (need_reverse && !isExternal) { - eloop->make_clockwise(); + eloop->reverse(); } } } @@ -1414,18 +1420,17 @@ void PerimeterGenerator::process_classic() // at this point, all loops should be in contours[0] bool steep_overhang_contour = false; bool steep_overhang_hole = false; - const WallDirection wall_direction = config->wall_direction; - if (wall_direction != WallDirection::Auto) { - // Skip steep overhang detection if wall direction is specified + if (!config->overhang_reverse) { + // Skip steep overhang detection no reverse is specified steep_overhang_contour = true; steep_overhang_hole = true; } ExtrusionEntityCollection entities = traverse_loops(*this, contours.front(), thin_walls, steep_overhang_contour, steep_overhang_hole); // All walls are counter-clockwise initially, so we don't need to reorient it if that's what we want - if (wall_direction != WallDirection::CounterClockwise) { + if (config->overhang_reverse) { reorient_perimeters(entities, steep_overhang_contour, steep_overhang_hole, // Reverse internal only if the wall direction is auto - this->config->overhang_reverse_internal_only && wall_direction == WallDirection::Auto); + this->config->overhang_reverse_internal_only); } // if brim will be printed, reverse the order of perimeters so that @@ -2444,18 +2449,15 @@ void PerimeterGenerator::process_arachne() bool steep_overhang_contour = false; bool steep_overhang_hole = false; - const WallDirection wall_direction = config->wall_direction; - if (wall_direction != WallDirection::Auto) { - // Skip steep overhang detection if wall direction is specified + if (!config->overhang_reverse) { + // Skip steep overhang detection no reverse is specified steep_overhang_contour = true; steep_overhang_hole = true; } if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions, steep_overhang_contour, steep_overhang_hole); !extrusion_coll.empty()) { - // All walls are counter-clockwise initially, so we don't need to reorient it if that's what we want - if (wall_direction != WallDirection::CounterClockwise) { + if (config->overhang_reverse) { reorient_perimeters(extrusion_coll, steep_overhang_contour, steep_overhang_hole, - // Reverse internal only if the wall direction is auto - this->config->overhang_reverse_internal_only && wall_direction == WallDirection::Auto); + this->config->overhang_reverse_internal_only); } this->loops->append(extrusion_coll); } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 070dc35215..3f60baeef4 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -246,7 +246,6 @@ CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(WallSequence) //Orca static t_config_enum_values s_keys_map_WallDirection{ - { "auto", int(WallDirection::Auto) }, { "ccw", int(WallDirection::CounterClockwise) }, { "cw", int(WallDirection::Clockwise)}, }; @@ -1987,14 +1986,12 @@ void PrintConfigDef::init_fff_params() def->category = L("Quality"); def->tooltip = L("The direction which the wall loops are extruded when looking down from the top.\n\nBy default all walls are extruded in counter-clockwise, unless Reverse on even is enabled. Set this to any option other than Auto will force the wall direction regardless of the Reverse on even.\n\nThis option will be disabled if spiral vase mode is enabled."); def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); - def->enum_values.push_back("auto"); def->enum_values.push_back("ccw"); def->enum_values.push_back("cw"); - def->enum_labels.push_back(L("Auto")); def->enum_labels.push_back(L("Counter clockwise")); def->enum_labels.push_back(L("Clockwise")); def->mode = comAdvanced; - def->set_default_value(new ConfigOptionEnum(WallDirection::Auto)); + def->set_default_value(new ConfigOptionEnum(WallDirection::CounterClockwise)); def = this->add("extruder", coInt); def->gui_type = ConfigOptionDef::GUIType::i_enum_open; @@ -7512,6 +7509,9 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va } else if (opt_key == "machine_switch_extruder_time") { opt_key = "machine_tool_change_time"; } + else if (opt_key == "wall_direction" && value == "auto") { + value = "ccw"; + } // Ignore the following obsolete configuration keys: static std::set ignore = { diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index cc0c765530..7942eadc67 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -113,7 +113,6 @@ enum class WallSequence { // Orca enum class WallDirection { - Auto, CounterClockwise, Clockwise, Count, diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 60828cedcf..ac2c073da5 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -327,7 +327,6 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con config->opt_int("enforce_support_layers") == 0 && ! config->opt_bool("detect_thin_wall") && ! config->opt_bool("overhang_reverse") && - config->opt_enum("wall_direction") == WallDirection::Auto && config->opt_enum("timelapse_type") == TimelapseType::tlTraditional && !config->opt_bool("enable_wrapping_detection"))) { @@ -342,7 +341,6 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con new_conf.set_key_value("enforce_support_layers", new ConfigOptionInt(0)); new_conf.set_key_value("detect_thin_wall", new ConfigOptionBool(false)); new_conf.set_key_value("overhang_reverse", new ConfigOptionBool(false)); - new_conf.set_key_value("wall_direction", new ConfigOptionEnum(WallDirection::Auto)); new_conf.set_key_value("timelapse_type", new ConfigOptionEnum(tlTraditional)); new_conf.set_key_value("enable_wrapping_detection", new ConfigOptionBool(false)); sparse_infill_density = 0; @@ -661,8 +659,6 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co toggle_field("top_shell_thickness", ! has_spiral_vase && has_top_shell); toggle_field("bottom_shell_thickness", ! has_spiral_vase && has_bottom_shell); - toggle_field("wall_direction", !has_spiral_vase); - // Gap fill is newly allowed in between perimeter lines even for empty infill (see GH #1476). toggle_field("gap_infill_speed", have_perimeters); @@ -891,8 +887,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co bool has_detect_overhang_wall = config->opt_bool("detect_overhang_wall"); bool has_overhang_reverse = config->opt_bool("overhang_reverse"); - bool force_wall_direction = config->opt_enum("wall_direction") != WallDirection::Auto; - bool allow_overhang_reverse = !has_spiral_vase && !force_wall_direction; + bool allow_overhang_reverse = !has_spiral_vase; toggle_line("overhang_reverse", allow_overhang_reverse); toggle_line("overhang_reverse_internal_only", allow_overhang_reverse && has_overhang_reverse); bool has_overhang_reverse_internal_only = config->opt_bool("overhang_reverse_internal_only"); diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 6ee0733abd..b910e1ebbf 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -2744,7 +2744,6 @@ void PartPlate::set_vase_mode_related_object_config(int obj_id) { new_conf.set_key_value("detect_thin_wall", new ConfigOptionBool(false)); new_conf.set_key_value("timelapse_type", new ConfigOptionEnum(tlTraditional)); new_conf.set_key_value("overhang_reverse", new ConfigOptionBool(false)); - new_conf.set_key_value("wall_direction", new ConfigOptionEnum(WallDirection::Auto)); auto applying_keys = global_config->diff(new_conf); for (ModelObject* object : obj_ptrs) { From 7ae93733684b63c7bdfd092a4ef617900777a86c Mon Sep 17 00:00:00 2001 From: vovodroid Date: Sun, 6 Apr 2025 19:54:01 +0300 Subject: [PATCH 2/2] Alternate internal walls --- src/libslic3r/GCode.cpp | 11 ++- src/libslic3r/GCode/SeamPlacer.cpp | 9 ++- src/libslic3r/GCode/SeamPlacer.hpp | 2 +- src/libslic3r/PerimeterGenerator.cpp | 110 ++++++++++++++++++++------ src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 25 +++--- src/libslic3r/PrintConfig.hpp | 2 +- src/libslic3r/PrintObject.cpp | 2 +- src/slic3r/GUI/ConfigManipulation.cpp | 19 +++-- src/slic3r/GUI/Tab.cpp | 2 +- 10 files changed, 131 insertions(+), 53 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 37993966f0..72f99120ad 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -5385,7 +5385,16 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou float seam_overhang = std::numeric_limits::lowest(); if (!m_config.spiral_mode && description == "perimeter") { assert(m_layer != nullptr); - m_seam_placer.place_seam(m_layer, loop, last_pos, seam_overhang); + bool reverse = false; + + if (region_perimeters.size() > 1) { + ExtrusionLoop* p0 = dynamic_cast(region_perimeters[0]); + ExtrusionLoop* p1 = dynamic_cast(region_perimeters[1]); + if (p0 && p1) + reverse = p0->is_clockwise() != p1->is_clockwise(); + } + + m_seam_placer.place_seam(m_layer, loop, last_pos, seam_overhang, reverse); } else loop.split_at(last_pos, false); diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index b2b49ec6e7..f033c3422d 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -1494,7 +1494,7 @@ void SeamPlacer::init(const Print &print, std::function throw_if_can } void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, - const Point &last_pos, float& overhang) const { + const Point &last_pos, float& overhang, bool reverse) const { using namespace SeamPlacerImpl; const PrintObject *po = layer->object(); // Must not be called with supprot layer. @@ -1596,8 +1596,11 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, //lastly, for internal perimeters, do the staggering if requested if (po->config().staggered_inner_seams && loop.length() > 0.0) { - //fix depth, it is sometimes strongly underestimated - depth = std::max(loop.paths[projected_point.path_idx].width, depth); + if (!reverse) + //fix depth, it is sometimes strongly underestimated + depth = std::max(loop.paths[projected_point.path_idx].width, depth); + else + depth = std::min(4. + ((double)rand())/RAND_MAX*2., loop.length() * SCALING_FACTOR / 2); while (depth > 0.0f) { auto next_point = get_next_loop_point(projected_point); diff --git a/src/libslic3r/GCode/SeamPlacer.hpp b/src/libslic3r/GCode/SeamPlacer.hpp index 8a973d0d8a..f75d04ccb6 100644 --- a/src/libslic3r/GCode/SeamPlacer.hpp +++ b/src/libslic3r/GCode/SeamPlacer.hpp @@ -143,7 +143,7 @@ public: void init(const Print &print, std::function throw_if_canceled_func); - void place_seam(const Layer *layer, ExtrusionLoop &loop, const Point &last_pos, float& overhang) const; + void place_seam(const Layer *layer, ExtrusionLoop &loop, const Point &last_pos, float& overhang, bool reverse) const; private: void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info); void calculate_candidates_visibility(const PrintObject *po, diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 7da2f20725..8e671aa728 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -1092,30 +1092,85 @@ void PerimeterGenerator::apply_extra_perimeters(ExPolygons &infill_area) } // Reorient loop direction -static void reorient_perimeters(ExtrusionEntityCollection &entities, bool steep_overhang_contour, bool steep_overhang_hole, bool reverse_internal_only) +static void reorient_walls(ExtrusionEntitiesPtr &entities, bool steep_overhang_contour, bool steep_overhang_hole, + bool alternate_internal_walls) { - if (steep_overhang_hole || steep_overhang_contour) { - for (auto entity : entities) { + if (steep_overhang_contour || steep_overhang_hole || alternate_internal_walls) { + ExtrusionEntitiesPtr ordered = entities; + + if (alternate_internal_walls) { + auto entity = *ordered.begin(); if (entity->is_loop()) { ExtrusionLoop *eloop = static_cast(entity); - // Only reverse when needed - bool need_reverse = ((eloop->loop_role() & elrHole) == elrHole) ? steep_overhang_hole : steep_overhang_contour; - - bool isExternal = false; - if(reverse_internal_only){ - for(auto path : eloop->paths){ - if(path.role() == erExternalPerimeter){ - isExternal = true; - break; - } - } + for (auto path : eloop->paths) { + if (path.role() == erPerimeter) + std::reverse(ordered.begin(), ordered.end()); + break; } - - if (need_reverse && !isExternal) { - eloop->reverse(); + } + + if (ordered.size() > 2) { + entity = *ordered.begin(); + if (entity->is_loop()) { + ExtrusionLoop *eloop = static_cast(entity); + for (auto path : eloop->paths) { + if (path.role() == erPerimeter) + std::swap(*ordered.begin(), *(ordered.begin()+1)); + break; + } } } } + int reverse_count = 0; + for (auto entity : ordered) { + if (entity->is_loop()) { + ExtrusionLoop *eloop = static_cast(entity); + for(auto path : eloop->paths){ + if(path.role() == erExternalPerimeter){ + if (((eloop->loop_role() & elrHole) == elrHole) ? steep_overhang_hole : steep_overhang_contour) { + eloop->reverse(); + reverse_count++; + } + break; + } + if(path.role() == erPerimeter && alternate_internal_walls){ + reverse_count++; + if (reverse_count % 2 == 1) + eloop->reverse(); + break; + } + } + } + } + } +} + +static void reorient_perimeters(ExtrusionEntityCollection& entities, bool steep_overhang_contour, bool steep_overhang_hole, + bool alternate_internal_walls) +{ + alternate_internal_walls = alternate_internal_walls && entities.size() > 1; + + if (steep_overhang_contour || steep_overhang_hole || alternate_internal_walls) { + + if (alternate_internal_walls) { + ExtrusionEntitiesPtr walls; + + for (auto entity : entities) { + if (entity->is_loop()) { + ExtrusionLoop *eloop = static_cast(entity); + + if (walls.empty() || eloop->loop_role() == static_cast(walls.back())->loop_role()) + walls.push_back(entity); + else { + reorient_walls(walls, steep_overhang_contour, steep_overhang_hole, alternate_internal_walls); + walls.clear(); + walls.push_back(entity); + } + } + } + reorient_walls(walls, steep_overhang_contour, steep_overhang_hole, alternate_internal_walls); + } else + reorient_walls(entities.entities, steep_overhang_contour, steep_overhang_hole, alternate_internal_walls); } } @@ -1427,10 +1482,14 @@ void PerimeterGenerator::process_classic() } ExtrusionEntityCollection entities = traverse_loops(*this, contours.front(), thin_walls, steep_overhang_contour, steep_overhang_hole); // All walls are counter-clockwise initially, so we don't need to reorient it if that's what we want - if (config->overhang_reverse) { + if (config->overhang_reverse || this->config->alternate_internal_walls) { + if (!config->overhang_reverse) { + // Skip steep overhang reverse if not specified + steep_overhang_contour = false; + steep_overhang_hole = false; + } reorient_perimeters(entities, steep_overhang_contour, steep_overhang_hole, - // Reverse internal only if the wall direction is auto - this->config->overhang_reverse_internal_only); + this->config->alternate_internal_walls); } // if brim will be printed, reverse the order of perimeters so that @@ -2450,14 +2509,19 @@ void PerimeterGenerator::process_arachne() bool steep_overhang_contour = false; bool steep_overhang_hole = false; if (!config->overhang_reverse) { - // Skip steep overhang detection no reverse is specified + // Skip steep overhang detection if no reverse is specified steep_overhang_contour = true; steep_overhang_hole = true; } if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions, steep_overhang_contour, steep_overhang_hole); !extrusion_coll.empty()) { - if (config->overhang_reverse) { + + if (config->overhang_reverse || this->config->alternate_internal_walls){ + if (!config->overhang_reverse) { + steep_overhang_contour = false; + steep_overhang_hole = false; + } reorient_perimeters(extrusion_coll, steep_overhang_contour, steep_overhang_hole, - this->config->overhang_reverse_internal_only); + this->config->alternate_internal_walls); } this->loops->append(extrusion_coll); } diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 1dcdd83000..cdef82cc25 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -883,7 +883,7 @@ bool Preset::has_cali_lines(PresetBundle* preset_bundle) static std::vector s_Preset_print_options { "layer_height", "initial_layer_print_height", "wall_loops", "alternate_extra_wall", "slice_closing_radius", "spiral_mode", "spiral_mode_smooth", "spiral_mode_max_xy_smoothing", "spiral_starting_flow_ratio", "spiral_finishing_flow_ratio", "slicing_mode", "top_shell_layers", "top_shell_thickness", "top_surface_density", "bottom_surface_density", "bottom_shell_layers", "bottom_shell_thickness", - "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only", "wall_direction", + "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold", "wall_direction", "alternate_internal_walls", "seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density","fill_multiline", "sparse_infill_pattern", "lateral_lattice_angle_1", "lateral_lattice_angle_2", "infill_overhang_angle", "top_surface_pattern", "bottom_surface_pattern", "infill_direction", "solid_infill_direction", "counterbore_hole_bridging","infill_shift_step", "sparse_infill_rotate_template", "solid_infill_rotate_template", "symmetric_infill_y_axis","skeleton_infill_density", "infill_lock_depth", "skin_infill_depth", "skin_infill_density", "align_infill_direction_to_model", "extra_solid_infills", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 3f60baeef4..df6ca8d802 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1377,19 +1377,6 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(false)); - def = this->add("overhang_reverse_internal_only", coBool); - def->label = L("Reverse only internal perimeters"); - def->full_label = L("Reverse only internal perimeters"); - def->category = L("Quality"); - def->tooltip = L("Apply the reverse perimeters logic only on internal perimeters.\n\n" - "This setting greatly reduces part stresses as they are now distributed in alternating directions. " - "This should reduce part warping while also maintaining external wall quality. " - "This feature can be very useful for warp prone material, like ABS/ASA, and also for elastic filaments, like TPU and Silk PLA. " - "It can also help reduce warping on floating regions over supports.\n\nFor this setting to be the most effective, " - "it is recommended to set the Reverse Threshold to 0 so that all internal walls print in alternating directions on even layers irrespective of their overhang degree."); - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionBool(false)); - def = this->add("counterbore_hole_bridging", coEnum); def->label = L("Bridge counterbore holes"); def->category = L("Quality"); @@ -1993,6 +1980,14 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionEnum(WallDirection::CounterClockwise)); + def = this->add("alternate_internal_walls", coBool); + def->label = L("Reverse internal perimeters"); + def->full_label = L("Reverse internal perimeters"); + def->category = L("Quality"); + def->tooltip = L("Alternate each internal perimeter direction.\n\nThis setting greatly reduces part stresses as they are now distributed in alternating directions. This should reduce part warping while also maintaining external wall quality. This feature can be very useful for warp prone material, like ABS/ASA, and also for elastic filaments, like TPU and Silk PLA. It can also help reduce warping on floating regions over supports."); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + def = this->add("extruder", coInt); def->gui_type = ConfigOptionDef::GUIType::i_enum_open; def->label = L("Extruder"); @@ -7512,6 +7507,10 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va else if (opt_key == "wall_direction" && value == "auto") { value = "ccw"; } + else if (opt_key == "overhang_reverse_internal_only" && value == "1") { + opt_key = "alternate_internal_walls"; + value = "1"; + } // Ignore the following obsolete configuration keys: static std::set ignore = { diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 7942eadc67..cfc0e01be8 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1145,13 +1145,13 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloatOrPercent, hole_to_polyhole_threshold)) ((ConfigOptionBool, hole_to_polyhole_twisted)) ((ConfigOptionBool, overhang_reverse)) - ((ConfigOptionBool, overhang_reverse_internal_only)) ((ConfigOptionFloatOrPercent, overhang_reverse_threshold)) ((ConfigOptionEnum, counterbore_hole_bridging)) ((ConfigOptionEnum, wall_sequence)) ((ConfigOptionBool, is_infill_first)) ((ConfigOptionBool, small_area_infill_flow_compensation)) ((ConfigOptionEnum, wall_direction)) + ((ConfigOptionBool, alternate_internal_walls)) // Orca: flow ratios ((ConfigOptionBool, set_other_flow_ratios)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 7cc98209cf..a93ab2954f 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1266,9 +1266,9 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "fuzzy_skin_persistence" || opt_key == "detect_overhang_wall" || opt_key == "overhang_reverse" - || opt_key == "overhang_reverse_internal_only" || opt_key == "overhang_reverse_threshold" || opt_key == "wall_direction" + || opt_key == "alternate_internal_walls" || opt_key == "enable_overhang_speed" || opt_key == "detect_thin_wall" || opt_key == "precise_outer_wall") { diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index ac2c073da5..07fecb51b7 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -540,6 +540,15 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con apply(config, &new_conf); is_msg_dlg_already_exist = false; } + + if (config->opt_bool("alternate_internal_walls") && !config->opt_bool("staggered_inner_seams")) { + const wxString msg_text = _(L("Reverse interanal walls should be used with Staggered inner seams option.\n Set to on.")); + MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK); + DynamicPrintConfig new_conf = *config; + dialog.ShowModal(); + new_conf.set_key_value("staggered_inner_seams", new ConfigOptionBool(true)); + apply(config, &new_conf); + } } void ConfigManipulation::apply_null_fff_config(DynamicPrintConfig *config, std::vector const &keys, std::map const &configs) @@ -889,14 +898,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co bool has_overhang_reverse = config->opt_bool("overhang_reverse"); bool allow_overhang_reverse = !has_spiral_vase; toggle_line("overhang_reverse", allow_overhang_reverse); - toggle_line("overhang_reverse_internal_only", allow_overhang_reverse && has_overhang_reverse); - bool has_overhang_reverse_internal_only = config->opt_bool("overhang_reverse_internal_only"); - if (has_overhang_reverse_internal_only){ - DynamicPrintConfig new_conf = *config; - new_conf.set_key_value("overhang_reverse_threshold", new ConfigOptionFloatOrPercent(0,true)); - apply(config, &new_conf); - } - toggle_line("overhang_reverse_threshold", has_detect_overhang_wall && allow_overhang_reverse && has_overhang_reverse && !has_overhang_reverse_internal_only); + toggle_field("alternate_internal_walls", !has_spiral_vase && (config->opt_int("wall_loops") > 1)); + toggle_line("overhang_reverse_threshold", has_detect_overhang_wall && allow_overhang_reverse && has_overhang_reverse); toggle_line("timelapse_type", is_BBL_Printer); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index f5f90f1acc..108a501545 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2357,6 +2357,7 @@ void TabPrint::build() optgroup->append_single_option_line("wall_sequence", "quality_settings_wall_and_surfaces#walls-printing-order"); optgroup->append_single_option_line("is_infill_first", "quality_settings_wall_and_surfaces#print-infill-first"); optgroup->append_single_option_line("wall_direction", "quality_settings_wall_and_surfaces#wall-loop-direction"); + optgroup->append_single_option_line("alternate_internal_walls", "quality_settings_wall_and_surfaces#alternate-internal-walls"); optgroup->append_single_option_line("print_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); optgroup->append_single_option_line("top_solid_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); optgroup->append_single_option_line("bottom_solid_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio"); @@ -2401,7 +2402,6 @@ void TabPrint::build() optgroup->append_single_option_line("make_overhang_printable_hole_size", "quality_settings_overhangs#hole-area"); optgroup->append_single_option_line("extra_perimeters_on_overhangs", "quality_settings_overhangs#extra-perimeters-on-overhangs"); optgroup->append_single_option_line("overhang_reverse", "quality_settings_overhangs#reverse-on-even"); - optgroup->append_single_option_line("overhang_reverse_internal_only", "quality_settings_overhangs#reverse-internal-only"); optgroup->append_single_option_line("overhang_reverse_threshold", "quality_settings_overhangs#reverse-threshold"); page = add_options_page(L("Strength"), "custom-gcode_strength"); // ORCA: icon only visible on placeholders