diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 06887c769..1a29a11ef 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -236,6 +236,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Do not use the 'Avoid crossing perimeters' on the first layer."); def->mode = comExpert; def->set_default_value(new ConfigOptionBool(true)); + def = this->add("avoid_crossing_perimeters_max_detour", coFloatOrPercent); def->label = L("Avoid crossing perimeters - Max detour length"); def->category = OptionCategory::perimeter; @@ -5945,9 +5946,118 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const double max_nozzle_diameter = 0; for (double dmr : nozzle_diameter_option->values) max_nozzle_diameter = std::max(max_nozzle_diameter, dmr); - if (opt_key == "extrusion_width") { - ConfigOptionFloatOrPercent* spacing_option = this->option("extrusion_spacing"); - if (width_option) { + ConfigOptionFloatOrPercent* spacing_option = nullptr; + try { + if (opt_key == "extrusion_width") { + spacing_option = this->option("extrusion_spacing"); + if (width_option) { + width_option->set_phony(false); + spacing_option->set_phony(true); + Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); + spacing_option->percent = width_option->percent; + something_changed = true; + } + } + if (opt_key == "first_layer_extrusion_width") { + spacing_option = this->option("first_layer_extrusion_spacing"); + if (width_option) { + width_option->set_phony(false); + spacing_option->set_phony(true); + Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); + spacing_option->percent = width_option->percent; + something_changed = true; + } + } + if (opt_key == "perimeter_extrusion_width") { + const ConfigOptionPercent* perimeter_overlap_option = find_option("perimeter_overlap", this, config_collection); + spacing_option = this->option("perimeter_extrusion_spacing"); + if (width_option && perimeter_overlap_option) { + width_option->set_phony(false); + spacing_option->set_phony(true); + Flow flow = Flow::new_from_config_width(FlowRole::frExternalPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + flow.spacing_ratio = perimeter_overlap_option->get_abs_value(1); + spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); + spacing_option->percent = width_option->percent; + something_changed = true; + } + } + if (opt_key == "external_perimeter_extrusion_width") { + const ConfigOptionPercent* external_perimeter_overlap_option = find_option("external_perimeter_overlap", this, config_collection); + spacing_option = this->option("external_perimeter_extrusion_spacing"); + if (width_option && external_perimeter_overlap_option) { + width_option->set_phony(false); + spacing_option->set_phony(true); + Flow ext_perimeter_flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + ext_perimeter_flow.spacing_ratio = external_perimeter_overlap_option->get_abs_value(0.5); + spacing_option->value = (width_option->percent) ? std::round(100 * ext_perimeter_flow.spacing() / max_nozzle_diameter) : (std::round(ext_perimeter_flow.spacing() * 10000) / 10000); + spacing_option->percent = width_option->percent; + something_changed = true; + } + } + if (opt_key == "infill_extrusion_width") { + spacing_option = this->option("infill_extrusion_spacing"); + if (width_option) { + width_option->set_phony(false); + spacing_option->set_phony(true); + Flow flow = Flow::new_from_config_width(FlowRole::frInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); + spacing_option->percent = width_option->percent; + something_changed = true; + } + } + if (opt_key == "solid_infill_extrusion_width") { + spacing_option = this->option("solid_infill_extrusion_spacing"); + if (width_option) { + width_option->set_phony(false); + spacing_option->set_phony(true); + Flow flow = Flow::new_from_config_width(FlowRole::frSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); + spacing_option->percent = width_option->percent; + something_changed = true; + } + } + if (opt_key == "top_infill_extrusion_width") { + spacing_option = this->option("top_infill_extrusion_spacing"); + if (width_option) { + width_option->set_phony(false); + spacing_option->set_phony(true); + Flow flow = Flow::new_from_config_width(FlowRole::frTopSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); + spacing_option->percent = width_option->percent; + something_changed = true; + } + } + //if (opt_key == "support_material_extrusion_width") { + // Flow flow = Flow::new_from_config_width(FlowRole::frSupportMaterial, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + // if (width_option->percent) + // this->set_key_value("support_material_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(100 * flow.spacing() / max_nozzle_diameter), true)); + // else + // this->set_key_value("support_material_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(flow.spacing() * 10000) / 10000, false)); + // something_changed = true; + //} + //if (opt_key == "skirt_extrusion_width") { + // Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); + // if (width_option->percent) + // this->set_key_value("skirt_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(100 * flow.spacing() / max_nozzle_diameter), true)); + // else + // this->set_key_value("skirt_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(flow.spacing() * 10000) / 10000, false)); + // something_changed = true; + //} + } catch (FlowErrorNegativeSpacing) { + if (spacing_option != nullptr) { + width_option->set_phony(true); + spacing_option->set_phony(false); + spacing_option->value = 100; + spacing_option->percent = true; + Flow flow = Flow::new_from_spacing(spacing_option->get_abs_value(max_nozzle_diameter), max_nozzle_diameter, layer_height_option->value, false); + width_option->value = (spacing_option->percent) ? std::round(100 * flow.width / max_nozzle_diameter) : (std::round(flow.width * 10000) / 10000); + width_option->percent = spacing_option->percent; + something_changed = true; + } else { + width_option->value = 100; + width_option->percent = true; width_option->set_phony(false); spacing_option->set_phony(true); Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); @@ -5956,92 +6066,6 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const something_changed = true; } } - if (opt_key == "first_layer_extrusion_width") { - ConfigOptionFloatOrPercent* spacing_option = this->option("first_layer_extrusion_spacing"); - if (width_option) { - width_option->set_phony(false); - spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); - spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); - spacing_option->percent = width_option->percent; - something_changed = true; - } - } - if (opt_key == "perimeter_extrusion_width") { - const ConfigOptionPercent* perimeter_overlap_option = find_option("perimeter_overlap", this, config_collection); - ConfigOptionFloatOrPercent* spacing_option = this->option("perimeter_extrusion_spacing"); - if (width_option && perimeter_overlap_option) { - width_option->set_phony(false); - spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frExternalPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); - flow.spacing_ratio = perimeter_overlap_option->get_abs_value(1); - spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); - spacing_option->percent = width_option->percent; - something_changed = true; - } - } - if (opt_key == "external_perimeter_extrusion_width") { - const ConfigOptionPercent* external_perimeter_overlap_option = find_option("external_perimeter_overlap", this, config_collection); - ConfigOptionFloatOrPercent* spacing_option = this->option("external_perimeter_extrusion_spacing"); - if (width_option && external_perimeter_overlap_option) { - width_option->set_phony(false); - spacing_option->set_phony(true); - Flow ext_perimeter_flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); - ext_perimeter_flow.spacing_ratio = external_perimeter_overlap_option->get_abs_value(0.5); - spacing_option->value = (width_option->percent) ? std::round(100 * ext_perimeter_flow.spacing() / max_nozzle_diameter) : (std::round(ext_perimeter_flow.spacing() * 10000) / 10000); - spacing_option->percent = width_option->percent; - something_changed = true; - } - } - if (opt_key == "infill_extrusion_width") { - ConfigOptionFloatOrPercent* spacing_option = this->option("infill_extrusion_spacing"); - if (width_option) { - width_option->set_phony(false); - spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0); - spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); - spacing_option->percent = width_option->percent; - something_changed = true; - } - } - if (opt_key == "solid_infill_extrusion_width") { - ConfigOptionFloatOrPercent* spacing_option = this->option("solid_infill_extrusion_spacing"); - if (width_option) { - width_option->set_phony(false); - spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0); - spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); - spacing_option->percent = width_option->percent; - something_changed = true; - } - } - if (opt_key == "top_infill_extrusion_width") { - ConfigOptionFloatOrPercent* spacing_option = this->option("top_infill_extrusion_spacing"); - if (width_option) { - width_option->set_phony(false); - spacing_option->set_phony(true); - Flow flow = Flow::new_from_config_width(FlowRole::frTopSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0); - spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000); - spacing_option->percent = width_option->percent; - something_changed = true; - } - } - //if (opt_key == "support_material_extrusion_width") { - // Flow flow = Flow::new_from_config_width(FlowRole::frSupportMaterial, *width_option, max_nozzle_diameter, layer_height_option->value, 0); - // if (width_option->percent) - // this->set_key_value("support_material_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(100 * flow.spacing() / max_nozzle_diameter), true)); - // else - // this->set_key_value("support_material_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(flow.spacing() * 10000) / 10000, false)); - // something_changed = true; - //} - //if (opt_key == "skirt_extrusion_width") { - // Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0); - // if (width_option->percent) - // this->set_key_value("skirt_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(100 * flow.spacing() / max_nozzle_diameter), true)); - // else - // this->set_key_value("skirt_extrusion_spacing", new ConfigOptionFloatOrPercent(std::round(flow.spacing() * 10000) / 10000, false)); - // something_changed = true; - //} } } return something_changed; diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index be0a4f575..5f7ae0dfe 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -7,6 +7,7 @@ #include "MainFrame.hpp" #include "format.hpp" +#include "libslic3r/PresetBundle.hpp" #include "libslic3r/PrintConfig.hpp" #include @@ -328,33 +329,50 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true } else if (((m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max) || (m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1)) && (m_value.empty() || std::string(str.ToUTF8().data()) != boost::any_cast(m_value))) - { - if (!check_value) { - m_value.clear(); - break; - } + { + // exceptions + if (std::set{"infill_anchor", "infill_anchor_max", "avoid_crossing_perimeters_max_detour"}.count(m_opt.opt_key) > 0) { + m_value = std::string(str.ToUTF8().data()); + break; + } + if (m_opt.opt_key.find("extrusion_width") != std::string::npos || m_opt.opt_key.find("extrusion_spacing") != std::string::npos) { + const DynamicPrintConfig& printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config; + const std::vector &nozzle_diameters = printer_config.option("nozzle_diameter")->values; + double nozzle_diameter = 0; + for(double diameter : nozzle_diameters) + nozzle_diameter = std::max(nozzle_diameter, diameter); + if (val < nozzle_diameter * 10) { + m_value = std::string(str.ToUTF8().data()); + break; + } + } - bool infill_anchors = m_opt.opt_key == "infill_anchor" || m_opt.opt_key == "infill_anchor_max"; + if (!check_value) { + m_value.clear(); + break; + } - const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm"; - const wxString stVal = double_to_string(val, 2); - const wxString msg_text = from_u8((boost::format(_utf8(L("Do you mean %s%% instead of %s %s?\n" - "Select YES if you want to change this value to %s%%, \n" - "or NO if you are sure that %s %s is a correct value."))) % stVal % stVal % sidetext % stVal % stVal % sidetext).str()); - wxMessageDialog dialog(m_parent, msg_text, _(L("Parameter validation")) + ": " + m_opt_id , wxICON_WARNING | wxYES | wxNO); - if ((!infill_anchors || val > 100) && dialog.ShowModal() == wxID_YES) { - set_value(from_u8((boost::format("%s%%") % stVal).str()), false/*true*/); - str += "%%"; + bool infill_anchors = m_opt.opt_key == "infill_anchor" || m_opt.opt_key == "infill_anchor_max"; + + const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm"; + const wxString stVal = double_to_string(val, 2); + const wxString msg_text = from_u8((boost::format(_utf8(L("Do you mean %s%% instead of %s %s?\n" + "Select YES if you want to change this value to %s%%, \n" + "or NO if you are sure that %s %s is a correct value."))) % stVal % stVal % sidetext % stVal % stVal % sidetext).str()); + wxMessageDialog dialog(m_parent, msg_text, _(L("Parameter validation")) + ": " + m_opt_id , wxICON_WARNING | wxYES | wxNO); + if ((!infill_anchors || val > 100) && dialog.ShowModal() == wxID_YES) { + set_value(from_u8((boost::format("%s%%") % stVal).str()), false/*true*/); + str += "%%"; + } + else + set_value(stVal, false); // it's no needed but can be helpful, when inputted value contained "," instead of "." } - else - set_value(stVal, false); // it's no needed but can be helpful, when inputted value contained "," instead of "." } } - } m_value = std::string(str.ToUTF8().data()); - break; } - + break; + } case coPoints: { std::vector out_values; str.Replace(" ", wxEmptyString, true);