diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 9c2fe7f15..48f0d3ab2 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -66,6 +66,9 @@ void AppConfig::set_defaults() // Disable background processing by default as it is not stable. if (get("background_processing").empty()) set("background_processing", "0"); + // Enable support issues alerts by default + if (get("alert_when_supports_needed").empty()) + set("alert_when_supports_needed", "1"); // If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden. // By default, Prusa has the controller hidden. if (get("no_controller").empty()) diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 76f784d6d..d6a4692f3 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -444,7 +444,7 @@ static std::vector s_Preset_print_options { "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", "bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "first_layer_speed_over_raft", "perimeter_acceleration", "infill_acceleration", "bridge_acceleration", "first_layer_acceleration", "first_layer_acceleration_over_raft", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield", - "min_skirt_length", "brim_width", "brim_separation", "brim_type", "check_for_issues_mode", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", + "min_skirt_length", "brim_width", "brim_separation", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_closing_radius", "support_material_style", "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", "support_material_bottom_interface_layers", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 468e4c3d1..6bf468571 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -841,6 +841,8 @@ void Print::process() obj->ironing(); for (PrintObject *obj : m_objects) obj->generate_support_spots(); + for (PrintObject *obj : m_objects) + obj->alert_when_supports_needed(); for (PrintObject *obj : m_objects) obj->generate_support_material(); for (PrintObject *obj : m_objects) diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 7297cdfd5..b71b98578 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -64,7 +64,7 @@ enum PrintStep : unsigned int { enum PrintObjectStep : unsigned int { posSlice, posPerimeters, posPrepareInfill, - posInfill, posIroning, posSupportSpotsSearch, posSupportMaterial, posEstimateCurledExtrusions, posCount, + posInfill, posIroning, posSupportSpotsSearch, posAlertWhenSupportsNeeded, posSupportMaterial, posEstimateCurledExtrusions, posCount, }; // A PrintRegion object represents a group of volumes to print @@ -205,6 +205,7 @@ public: struct GeneratedSupportPoints{ Transform3d object_transform; // for frontend object mapping SupportSpotsGenerator::SupportPoints support_points; + SupportSpotsGenerator::PartialObjects partial_objects; }; std::vector> all_regions; @@ -370,6 +371,7 @@ private: void infill(); void ironing(); void generate_support_spots(); + void alert_when_supports_needed(); void generate_support_material(); void estimate_curled_extrusions(); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 45da5508d..c0d065832 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2589,14 +2589,6 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionEnum(SlicingMode::Regular)); - def = this->add("check_for_issues_mode", coBool); - def->label = L("Check for issues: "); - def->category = L("Support material"); - def->tooltip = L("Check for supportable issues that may appear during printing. " - "If enabled, slicer will make alerts when it detects " - "issues that may be resolved with supports and/or brim."); - def->set_default_value(new ConfigOptionBool(true)); - def = this->add("support_material", coBool); def->label = L("Generate support material"); def->category = L("Support material"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index bdf82e3be..6bfc7723d 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -516,7 +516,6 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionInt, wall_distribution_count)) ((ConfigOptionFloatOrPercent, min_feature_size)) ((ConfigOptionFloatOrPercent, min_bead_width)) - ((ConfigOptionBool, check_for_issues_mode)) ((ConfigOptionBool, support_material)) // Automatic supports (generated based fdm support point generator). ((ConfigOptionBool, support_material_auto)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 8fc016950..f44fdba5f 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -417,7 +417,7 @@ void PrintObject::generate_support_spots() { if (this->set_started(posSupportSpotsSearch)) { BOOST_LOG_TRIVIAL(debug) << "Searching support spots - start"; - m_print->set_status(75, L("Searching support spots")); + m_print->set_status(65, L("Searching support spots")); if (!this->shared_regions()->generated_support_points.has_value()) { PrintTryCancel cancel_func = m_print->make_try_cancel(); SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values, @@ -425,58 +425,71 @@ void PrintObject::generate_support_spots() this->config().raft_layers.getInt(), this->config().brim_type.value, float(this->config().brim_width.getFloat())}; auto [supp_points, partial_objects] = SupportSpotsGenerator::full_search(this, cancel_func, params); - this->m_shared_regions->generated_support_points = {this->trafo_centered(), supp_points}; + this->m_shared_regions->generated_support_points = {this->trafo_centered(), supp_points, partial_objects}; m_print->throw_if_canceled(); - - auto alert_fn = [&](PrintStateBase::WarningLevel level, SupportSpotsGenerator::SupportPointCause cause) { - switch (cause) { - case SupportSpotsGenerator::SupportPointCause::LongBridge: - this->active_step_add_warning(level, L("There are bridges longer than recommended length. Consider adding supports. ") + - (L("Object name")) + ": " + this->model_object()->name); - break; - case SupportSpotsGenerator::SupportPointCause::FloatingBridgeAnchor: - this->active_step_add_warning(level, L("Unsupported bridges will collapse. Supports are needed. ") + (L("Object name")) + - ": " + this->model_object()->name); - break; - case SupportSpotsGenerator::SupportPointCause::FloatingExtrusion: - if (level == PrintStateBase::WarningLevel::CRITICAL) { - this->active_step_add_warning(level, L("Clusters of unsupported extrusions found. Supports are needed. ") + - (L("Object name")) + ": " + this->model_object()->name); - } else { - this->active_step_add_warning(level, L("Some unspported extrusions found. Consider adding supports. ") + - (L("Object name")) + ": " + this->model_object()->name); - } - break; - case SupportSpotsGenerator::SupportPointCause::SeparationFromBed: - this->active_step_add_warning(level, L("Object part may break from the bed. Consider adding brim and/or supports. ") + - (L("Object name")) + ": " + this->model_object()->name); - break; - case SupportSpotsGenerator::SupportPointCause::UnstableFloatingPart: - this->active_step_add_warning(level, L("Floating object parts detected. Supports are needed. ") + (L("Object name")) + - ": " + this->model_object()->name); - break; - case SupportSpotsGenerator::SupportPointCause::WeakObjectPart: - this->active_step_add_warning(level, L("Thin parts of the object may break. Consider adding supports. ") + - (L("Object name")) + ": " + this->model_object()->name); - break; - } - }; - - if (!this->has_support() && this->config().check_for_issues_mode.getBool()) { - SupportSpotsGenerator::raise_alerts_for_issues(supp_points, partial_objects, alert_fn); - } } BOOST_LOG_TRIVIAL(debug) << "Searching support spots - end"; this->set_done(posSupportSpotsSearch); } } +void PrintObject::alert_when_supports_needed() +{ + if (this->set_started(posAlertWhenSupportsNeeded)) { + BOOST_LOG_TRIVIAL(debug) << "posAlertWhenSupportsNeeded - start"; + m_print->set_status(69, L("Alert if supports needed")); + + auto alert_fn = [&](PrintStateBase::WarningLevel level, SupportSpotsGenerator::SupportPointCause cause) { + switch (cause) { + case SupportSpotsGenerator::SupportPointCause::LongBridge: + this->active_step_add_warning(level, L("There are bridges longer than recommended length. Consider adding supports. ") + + (L("Object name")) + ": " + this->model_object()->name); + break; + case SupportSpotsGenerator::SupportPointCause::FloatingBridgeAnchor: + this->active_step_add_warning(level, L("Unsupported bridges will collapse. Supports are needed. ") + (L("Object name")) + + ": " + this->model_object()->name); + break; + case SupportSpotsGenerator::SupportPointCause::FloatingExtrusion: + if (level == PrintStateBase::WarningLevel::CRITICAL) { + this->active_step_add_warning(level, L("Clusters of unsupported extrusions found. Supports are needed. ") + + (L("Object name")) + ": " + this->model_object()->name); + } else { + this->active_step_add_warning(level, L("Some unspported extrusions found. Consider adding supports. ") + + (L("Object name")) + ": " + this->model_object()->name); + } + break; + case SupportSpotsGenerator::SupportPointCause::SeparationFromBed: + this->active_step_add_warning(level, L("Object part may break from the bed. Consider adding brim and/or supports. ") + + (L("Object name")) + ": " + this->model_object()->name); + break; + case SupportSpotsGenerator::SupportPointCause::UnstableFloatingPart: + this->active_step_add_warning(level, L("Floating object parts detected. Supports are needed. ") + (L("Object name")) + + ": " + this->model_object()->name); + break; + case SupportSpotsGenerator::SupportPointCause::WeakObjectPart: + this->active_step_add_warning(level, L("Thin parts of the object may break. Consider adding supports. ") + + (L("Object name")) + ": " + this->model_object()->name); + break; + } + }; + + if (!this->has_support() && this->m_shared_regions->generated_support_points.has_value()) { + SupportSpotsGenerator::SupportPoints supp_points = this->m_shared_regions->generated_support_points->support_points; + SupportSpotsGenerator::PartialObjects partial_objects = this->m_shared_regions->generated_support_points->partial_objects; + SupportSpotsGenerator::raise_alerts_for_issues(supp_points, partial_objects, alert_fn); + } + + BOOST_LOG_TRIVIAL(debug) << "posAlertWhenSupportsNeeded - end"; + this->set_done(posSupportSpotsSearch); + } +} + void PrintObject::generate_support_material() { if (this->set_started(posSupportMaterial)) { this->clear_support_layers(); if ((this->has_support() && m_layers.size() > 1) || (this->has_raft() && ! m_layers.empty())) { - m_print->set_status(85, L("Generating support material")); + m_print->set_status(70, L("Generating support material")); this->_generate_support_material(); m_print->throw_if_canceled(); } else { @@ -619,8 +632,6 @@ bool PrintObject::invalidate_state_by_config_options( steps.emplace_back(posSupportSpotsSearch); // Brim is printed below supports, support invalidates brim and skirt. steps.emplace_back(posSupportMaterial); - }else if (opt_key == "check_for_issues_mode") { - steps.emplace_back(posSupportSpotsSearch); } else if ( opt_key == "perimeters" || opt_key == "extra_perimeters" @@ -834,17 +845,20 @@ bool PrintObject::invalidate_step(PrintObjectStep step) // propagate to dependent steps if (step == posPerimeters) { - invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning, posSupportSpotsSearch, posEstimateCurledExtrusions }); + invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning, posSupportSpotsSearch, posAlertWhenSupportsNeeded, posEstimateCurledExtrusions }); invalidated |= m_print->invalidate_steps({ psSkirtBrim }); } else if (step == posPrepareInfill) { - invalidated |= this->invalidate_steps({ posInfill, posIroning, posSupportSpotsSearch }); + invalidated |= this->invalidate_steps({ posInfill, posIroning, posSupportSpotsSearch, posAlertWhenSupportsNeeded }); } else if (step == posInfill) { - invalidated |= this->invalidate_steps({ posIroning, posSupportSpotsSearch }); + invalidated |= this->invalidate_steps({ posIroning, posSupportSpotsSearch, posAlertWhenSupportsNeeded }); invalidated |= m_print->invalidate_steps({ psSkirtBrim }); } else if (step == posSlice) { - invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportSpotsSearch, posSupportMaterial, posEstimateCurledExtrusions }); + invalidated |= this->invalidate_steps({posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportSpotsSearch, + posAlertWhenSupportsNeeded, posSupportMaterial, posEstimateCurledExtrusions}); invalidated |= m_print->invalidate_steps({ psSkirtBrim }); m_slicing_params.valid = false; + } else if (step == posSupportSpotsSearch) { + invalidated |= posAlertWhenSupportsNeeded; } else if (step == posSupportMaterial) { invalidated |= m_print->invalidate_steps({ psSkirtBrim, }); invalidated |= this->invalidate_steps({ posEstimateCurledExtrusions }); diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index c8da11d95..fb824707c 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -256,15 +256,14 @@ std::vector check_extrusion_entity_stability(const ExtrusionEntit for (size_t i = 0; i < annotated_points.size(); ++i) { ExtendedPoint &curr_point = annotated_points[i]; - ExtendedPoint &prev_point = i > 0 ? annotated_points[i] : annotated_points[i - 1]; + const ExtendedPoint &prev_point = i > 0 ? annotated_points[i - 1] : annotated_points[i]; SupportPointCause potential_cause = std::abs(curr_point.curvature) > 0.1 ? SupportPointCause::FloatingBridgeAnchor : SupportPointCause::LongBridge; - float line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f; + float line_len = (prev_point.position - curr_point.position).norm(); Vec2d line_dir = line_len > EPSILON ? Vec2d((curr_point.position - prev_point.position) / double(line_len)) : Vec2d::Zero(); - ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast() : curr_point.position.cast(), - curr_point.position.cast(), line_len, entity}; + ExtrusionLine line_out{prev_point.position.cast(), curr_point.position.cast(), line_len, entity}; float max_bridge_len = std::max(params.support_points_interface_radius * 2.0f, params.bridge_distance / @@ -308,10 +307,10 @@ std::vector check_extrusion_entity_stability(const ExtrusionEntit float bridged_distance = annotated_points.front().position != annotated_points.back().position ? (params.bridge_distance + 1.0f) : 0.0f; for (size_t i = 0; i < annotated_points.size(); ++i) { - ExtendedPoint &curr_point = annotated_points[i]; - float line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f; - ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast() : curr_point.position.cast(), - curr_point.position.cast(), line_len, entity}; + ExtendedPoint &curr_point = annotated_points[i]; + const ExtendedPoint &prev_point = i > 0 ? annotated_points[i - 1] : annotated_points[i]; + float line_len = (prev_point.position - curr_point.position).norm(); + ExtrusionLine line_out{prev_point.position.cast(), curr_point.position.cast(), line_len, entity}; const ExtrusionLine nearest_prev_layer_line = prev_layer_lines.get_lines().size() > 0 ? prev_layer_lines.get_line(curr_point.nearest_prev_layer_line) : diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index cbe1805ee..c06947565 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -53,7 +53,7 @@ static SettingsFactory::Bundle FREQ_SETTINGS_BUNDLE_FFF = { { L("Layers and Perimeters"), { "layer_height" , "perimeters", "top_solid_layers", "bottom_solid_layers" } }, { L("Infill") , { "fill_density", "fill_pattern" } }, - { L("Support material") , { "check_for_issues_mode", "support_material", "support_material_auto", "support_material_threshold", + { L("Support material") , { "support_material", "support_material_auto", "support_material_threshold", "support_material_pattern", "support_material_interface_pattern", "support_material_buildplate_only", "support_material_spacing" } }, { L("Wipe options") , { "wipe_into_infill", "wipe_into_objects" } } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index c966f942b..fee9b3d27 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4271,7 +4271,12 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) this->preview->reload_print(); } - if (evt.status.flags & (PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS | PrintBase::SlicingStatus::UPDATE_PRINT_OBJECT_STEP_WARNINGS)) { + if ((evt.status.flags & PrintBase::SlicingStatus::UPDATE_PRINT_OBJECT_STEP_WARNINGS) && + static_cast(evt.status.warning_step) == posAlertWhenSupportsNeeded && + get_app_config()->get("alert_when_supports_needed") != "1") { + // This alerts are from posAlertWhenSupportsNeeded and the respective app settings is not Enabled, so discard the alerts. + } else if (evt.status.flags & + (PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS | PrintBase::SlicingStatus::UPDATE_PRINT_OBJECT_STEP_WARNINGS)) { // Update notification center with warnings of object_id and its warning_step. ObjectID object_id = evt.status.warning_object_id; int warning_step = evt.status.warning_step; diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 3830ba75e..1b2c68bdd 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -273,6 +273,14 @@ void PreferencesDialog::build() "as they\'re loaded in order to save time when exporting G-code."), app_config->get("background_processing") == "1"); + append_bool_option(m_optgroup_general, "alert_when_supports_needed", + L("Alert when supports needed"), + L("If this is enabled, Slic3r will raise alerts when it detects " + "issues in the sliced object, that can be resolved with supports (and brim). " + "Examples of such issues are floating object parts, unsupported extrusions and low bed adhesion."), + app_config->get("alert_when_supports_needed") == "1"); + + m_optgroup_general->append_separator(); // Please keep in sync with ConfigWizard diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index e9c854774..43eaa1a22 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1495,7 +1495,6 @@ void TabPrint::build() page = add_options_page(L("Support material"), "support"); category_path = "support-material_1698#"; optgroup = page->new_optgroup(L("Support material")); - optgroup->append_single_option_line("check_for_issues_mode", category_path + "check-for-issues-mode"); optgroup->append_single_option_line("support_material", category_path + "generate-support-material"); optgroup->append_single_option_line("support_material_auto", category_path + "auto-generated-supports"); optgroup->append_single_option_line("support_material_threshold", category_path + "overhang-threshold");