H2D X2D Multi Nozzle Size Printing Support (#14125)

This commit is contained in:
LixNix
2026-10-08 20:28:32 +08:00
committed by GitHub
parent 776ca6a3e4
commit 7d44b60ae4
13 changed files with 63 additions and 44 deletions
+2 -2
View File
@@ -1073,7 +1073,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
//get locked region param
if (params.pattern == ipLockedZag){
const PrintObject *object = layerm.layer()->object();
auto nozzle_diameter = float(object->print()->config().nozzle_diameter.get_at(layerm.region().extruder(extrusion_role) - 1));
auto nozzle_diameter = float(nozzle_diameter_for_filament(object->print()->config(), layerm.region().extruder(extrusion_role), object->print()->is_BBL_printer()));
Flow skin_flow = params.bridge ? params.flow : Flow::new_from_config_width(extrusion_role, region_config.skin_infill_line_width, nozzle_diameter, float((surface.thickness == -1) ? layer.height : surface.thickness));
//add skin flow
append_flow_param(lock_param.skin_flow_params, skin_flow, surface.expolygon);
@@ -1788,7 +1788,7 @@ void Layer::make_ironing()
// Create the ironing extrusions for regions <i, j)
ExPolygons ironing_areas;
double nozzle_dmr = this->object()->print()->config().nozzle_diameter.get_at(ironing_params.extruder - 1);
double nozzle_dmr = nozzle_diameter_for_filament(this->object()->print()->config(), ironing_params.extruder, this->object()->print()->is_BBL_printer());
if (ironing_params.just_infill) {
//TODO just_infill is currently not used.
// Just infill.
+4 -4
View File
@@ -241,14 +241,14 @@ Flow support_material_flow(const PrintObject *object, float layer_height)
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(object->config().support_line_width.value > 0) ? object->config().support_line_width : object->config().line_width,
// if object->config().support_filament == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
float(object->print()->config().nozzle_diameter.get_at(object->config().support_filament-1)),
float(nozzle_diameter_for_filament(object->print()->config(), object->config().support_filament, object->print()->is_BBL_printer())),
(layer_height > 0.f) ? layer_height : float(object->config().layer_height.value));
}
//BBS
Flow support_transition_flow(const PrintObject* object)
{
//BBS: support transition of tree support is bridge flow
float dmr = float(object->print()->config().nozzle_diameter.get_at(object->config().support_filament - 1));
float dmr = float(nozzle_diameter_for_filament(object->print()->config(), object->config().support_filament, object->print()->is_BBL_printer()));
return Flow::bridging_flow(dmr, dmr);
}
@@ -260,7 +260,7 @@ Flow support_material_1st_layer_flow(const PrintObject *object, float layer_heig
frSupportMaterial,
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(width.value > 0) ? width : object->config().line_width,
float(print_config.nozzle_diameter.get_at(object->config().support_filament-1)),
float(nozzle_diameter_for_filament(print_config, object->config().support_filament, object->print()->is_BBL_printer())),
(layer_height > 0.f) ? layer_height : float(print_config.initial_layer_print_height.value));
}
@@ -271,7 +271,7 @@ Flow support_material_interface_flow(const PrintObject *object, float layer_heig
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(object->config().support_line_width > 0) ? object->config().support_line_width : object->config().line_width,
// if object->config().support_interface_filament == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
float(object->print()->config().nozzle_diameter.get_at(object->config().support_interface_filament-1)),
float(nozzle_diameter_for_filament(object->print()->config(), object->config().support_interface_filament, object->print()->is_BBL_printer())),
(layer_height > 0.f) ? layer_height : float(object->config().layer_height.value));
}
+1 -1
View File
@@ -62,7 +62,7 @@ Flow LayerRegion::bridging_flow(FlowRole role, bool thick_bridge) const
const PrintObject &print_object = *this->layer()->object();
Flow bridge_flow;
// Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will fall back to zero'th element, so everything is all right.
auto nozzle_diameter = float(print_object.print()->config().nozzle_diameter.get_at(region.extruder(role) - 1));
auto nozzle_diameter = float(nozzle_diameter_for_filament(print_object.print()->config(), region.extruder(role), print_object.print()->is_BBL_printer()));
const ConfigOptionFloatOrPercent& bridge_width_opt = region_config.bridge_line_width;
const double bridge_width = bridge_width_opt.get_abs_value(nozzle_diameter);
const bool has_bridge_width = bridge_width > 0.;
+9 -8
View File
@@ -2229,7 +2229,7 @@ StringObjectException Print::validate(std::vector<StringObjectException> *warnin
for (const PrintRegion &region : object->all_regions()) {
const auto &bridge_width_opt = region.config().bridge_line_width;
for (FlowRole bridge_role : { frPerimeter, frInfill, frSolidInfill, frTopSolidInfill }) {
const double nozzle_diameter = m_config.nozzle_diameter.get_at(region.extruder(bridge_role) - 1);
const double nozzle_diameter = nozzle_diameter_for_filament(m_config, region.extruder(bridge_role), this->is_BBL_printer());
const double bridge_width = bridge_width_opt.get_abs_value(nozzle_diameter);
if (bridge_width <= 0.)
continue;
@@ -2606,7 +2606,7 @@ Flow Print::brim_flow() const
frPerimeter,
// Flow::new_from_config_width takes care of the percent to value substitution
width,
(float)m_config.nozzle_diameter.get_at(m_print_regions.front()->config().outer_wall_filament_id-1),
(float)nozzle_diameter_for_filament(m_config, m_print_regions.front()->config().outer_wall_filament_id, this->is_BBL_printer()),
(float)this->skirt_first_layer_height());
}
@@ -2623,12 +2623,13 @@ Flow Print::skirt_flow() const
extruders and take the one with, say, the smallest index;
The same logic should be applied to the code that selects the extruder during G-code
generation as well. */
return Flow::new_from_config_width(frPerimeter,
// Flow::new_from_config_width takes care of the percent to value substitution
width,
(float) m_config.nozzle_diameter.get_at(
m_objects.empty() ? 0 : m_objects.front()->config().support_filament - 1),
(float) this->skirt_first_layer_height());
return Flow::new_from_config_width(
frPerimeter,
// Flow::new_from_config_width takes care of the percent to value substitution
width,
// ORCA: resolve the actual nozzle the support filament is printed with (dual-nozzle printers).
(float)nozzle_diameter_for_filament(m_config, m_objects.empty() ? 0 : m_objects.front()->config().support_filament, this->is_BBL_printer()),
(float)this->skirt_first_layer_height());
}
bool Print::has_support_material() const
+9
View File
@@ -133,6 +133,15 @@ size_t get_extruder_index(const GCodeConfig& config, unsigned int filament_id)
return 0;
}
double nozzle_diameter_for_filament(const PrintConfig& config, int filament_id, bool is_bbl_printer)
{
int extruder = filament_id;
if (is_bbl_printer && config.nozzle_diameter.size() > 1 &&
filament_id >= 1 && static_cast<size_t>(filament_id - 1) < config.filament_map.size())
extruder = config.filament_map.get_at(filament_id - 1);
return config.nozzle_diameter.get_at(extruder - 1);
}
// Orca: input shaping values types by flavor
std::vector<std::string> get_shaper_type_values_for_flavor(GCodeFlavor flavor)
+2
View File
@@ -2566,6 +2566,8 @@ static bool has_zero_flush_volume_for_used_filaments(const std::vector<T> &fv_ma
size_t get_extruder_index(const GCodeConfig& config, unsigned int filament_id);
double nozzle_diameter_for_filament(const PrintConfig& config, int filament_id, bool is_bbl_printer);
} // namespace Slic3r
// Serialization through the Cereal library
+2 -2
View File
@@ -4467,8 +4467,8 @@ void PrintObject::combine_infill()
// Limit the number of combined layers to the maximum height allowed by this regions' nozzle.
//FIXME limit the layer height to max_layer_height
double nozzle_diameter = std::min(
this->print()->config().nozzle_diameter.get_at(region.config().sparse_infill_filament_id.value - 1),
this->print()->config().nozzle_diameter.get_at(region.config().internal_solid_filament_id.value - 1));
nozzle_diameter_for_filament(this->print()->config(), region.config().sparse_infill_filament_id.value, this->print()->is_BBL_printer()),
nozzle_diameter_for_filament(this->print()->config(), region.config().internal_solid_filament_id.value, this->print()->is_BBL_printer()));
//Orca: Limit combination of infill to up to infill_combination_max_layer_height
const double infill_combination_max_layer_height = region.config().infill_combination_max_layer_height.get_abs_value(nozzle_diameter);
+1 -1
View File
@@ -57,7 +57,7 @@ Flow PrintRegion::flow(const PrintObject &object, FlowRole role, double layer_he
// Get the configured nozzle_diameter for the extruder associated to the flow role requested.
// Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will follback to zero'th element, so everything is all right.
auto nozzle_diameter = float(print_config.nozzle_diameter.get_at(this->extruder(role) - 1));
auto nozzle_diameter = float(nozzle_diameter_for_filament(print_config, this->extruder(role), object.print()->is_BBL_printer()));
return Flow::new_from_config_width(role, config_width, nozzle_diameter, float(layer_height));
}
+1 -1
View File
@@ -2180,7 +2180,7 @@ SupportGeneratorLayersPtr PrintObjectSupportMaterial::top_contact_layers(
// check if the sharp tails should be extended higher
bool detect_first_sharp_tail_only = false;
const coordf_t extrusion_width = m_object_config->line_width.get_abs_value(object.print()->config().nozzle_diameter.get_at(object.config().support_interface_filament-1));
const coordf_t extrusion_width = m_object_config->line_width.get_abs_value(nozzle_diameter_for_filament(object.print()->config(), object.config().support_interface_filament, object.print()->is_BBL_printer()));
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
if (is_auto(m_object_config->support_type.value) && g_config_support_sharp_tails && !detect_first_sharp_tail_only) {
for (size_t layer_nr = layer_id_start; layer_nr < num_layers; layer_nr++) {
+1 -1
View File
@@ -1399,7 +1399,7 @@ void TreeSupport::generate_toolpaths()
{
const PrintObjectConfig &object_config = m_object->config();
coordf_t support_extrusion_width = m_support_params.support_extrusion_width;
coordf_t nozzle_diameter = m_print_config->nozzle_diameter.get_at(object_config.support_filament - 1);
coordf_t nozzle_diameter = nozzle_diameter_for_filament(*m_print_config, object_config.support_filament, m_object->print()->is_BBL_printer());
coordf_t layer_height = object_config.layer_height.value;
const size_t wall_count = object_config.tree_support_wall_count.value;
+8 -2
View File
@@ -1012,7 +1012,10 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
float machine_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
if (machine_diameter == 0.0f && preset_bundle) {
const ConfigOption *opt = preset_bundle->printers.get_selected_preset().config.option("nozzle_diameter");
if (opt) machine_diameter = static_cast<const ConfigOptionFloats *>(opt)->values[0];
if (opt) {
const auto &nd = static_cast<const ConfigOptionFloats *>(opt)->values;
if (!nd.empty()) machine_diameter = nd.size() > 1 ? nd[1] : nd[0];
}
}
stream << std::fixed << std::setprecision(1) << machine_diameter;
std::string nozzle_diameter_str = stream.str();
@@ -1291,7 +1294,10 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
float machine_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
if (machine_diameter == 0.0f) {
const ConfigOption *opt = preset_bundle->printers.get_selected_preset().config.option("nozzle_diameter");
if (opt) machine_diameter = static_cast<const ConfigOptionFloats *>(opt)->values[0];
if (opt) {
const auto &nd = static_cast<const ConfigOptionFloats *>(opt)->values;
if (!nd.empty()) machine_diameter = nd.size() > 1 ? nd[1] : nd[0];
}
}
stream << std::fixed << std::setprecision(1) << machine_diameter;
}
+21 -21
View File
@@ -1862,27 +1862,22 @@ bool Sidebar::priv::switch_diameter(bool single)
auto diameter_left = left_extruder->combo_diameter->GetValue();
auto diameter_right = right_extruder->combo_diameter->GetValue();
if (diameter_left != diameter_right) {
std::string printer_type = wxGetApp().preset_bundle->printers.get_edited_preset().get_printer_type(wxGetApp().preset_bundle);
auto left_name = _L(DevPrinterConfigUtil::get_toolhead_display_name(printer_type, DEPUTY_EXTRUDER_ID, ToolHeadComponent::Nozzle, ToolHeadNameCase::SentenceCase));
auto right_name = _L(DevPrinterConfigUtil::get_toolhead_display_name(printer_type, MAIN_EXTRUDER_ID, ToolHeadComponent::Nozzle, ToolHeadNameCase::SentenceCase));
MessageDialog dlg(this->plater,
_L("The software does not support using different diameter of nozzles for one print. "
"If the left and right nozzles are inconsistent, we can only proceed with single-head printing. "
"Please confirm which nozzle you would like to use for this project."),
_L("Switch diameter"), wxYES_NO | wxNO_DEFAULT);
dlg.SetButtonLabel(wxID_YES, wxString::Format("%s: %smm", left_name, diameter_left));
dlg.SetButtonLabel(wxID_NO, wxString::Format("%s: %smm", right_name, diameter_right));
int result = dlg.ShowModal();
if (result == wxID_YES)
diameter = diameter_left;
else if (result == wxID_NO)
diameter = diameter_right;
else
double left_value = 0.0, right_value = 0.0;
if (!diameter_left.ToCDouble(&left_value) || !diameter_right.ToCDouble(&right_value))
return false;
Tab* printer_tab = wxGetApp().get_tab(Preset::TYPE_PRINTER);
DynamicPrintConfig new_conf = wxGetApp().preset_bundle->printers.get_edited_preset().config;
auto* nozzle_diameter_opt = new_conf.option<ConfigOptionFloats>("nozzle_diameter");
if (printer_tab == nullptr || nozzle_diameter_opt == nullptr || nozzle_diameter_opt->size() < 2)
return false;
nozzle_diameter_opt->values[0] = left_value;
nozzle_diameter_opt->values[1] = right_value;
printer_tab->load_config(new_conf);
return true;
}
else {
diameter = diameter_left;
}
diameter = diameter_left;
}
return switch_diameter_to(diameter);
@@ -1892,15 +1887,20 @@ bool Sidebar::priv::switch_diameter_to(const wxString &diameter)
{
// ORCA: Check if the selected diameter matches the current nozzle diameter in the config
Preset& printer_preset = wxGetApp().preset_bundle->printers.get_edited_preset();
auto* nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(printer_preset.config.option("nozzle_diameter"));
// ORCA: the left/right combos of a BBL multi-nozzle printer set the nozzles apart without leaving
// the preset (see switch_diameter), so there the preset is only kept while every nozzle matches.
const bool nozzles_apart = nozzle_diameter && nozzle_diameter->size() > 1 && wxGetApp().preset_bundle->is_bbl_vendor() &&
std::any_of(nozzle_diameter->values.begin(), nozzle_diameter->values.end(),
[&diameter](double value) { return get_diameter_string(value) != diameter.ToStdString(); });
// The combo lists printer variants, and the variant of a mixed-nozzle machine ("0.4+0.6") is no
// single extruder's diameter, so the preset's own variant answers first.
const std::string &printer_variant = printer_preset.config.opt_string("printer_variant");
if (printer_variant == diameter.ToStdString()) {
if (printer_variant == diameter.ToStdString() && !nozzles_apart) {
return true;
}
// A named variant ("0.4 High Flow") shares its diameter with the standard profile, which selecting
// the plain diameter switches back to, so only a preset naming no variant is kept by its diameter.
auto* nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(printer_preset.config.option("nozzle_diameter"));
if (printer_variant.empty() && nozzle_diameter && nozzle_diameter->size() > 0) {
auto current_nozzle_dia = get_diameter_string(nozzle_diameter->values[0]);
// If the selected diameter is the same as current nozzle, don't switch profiles
+2 -1
View File
@@ -5833,7 +5833,8 @@ if (is_marlin_flavor)
// The page edits the extruder selected on the variant switch.
const size_t extruder_idx = size_t(get_current_active_extruder());
bool is_SEMM = m_config->opt_bool("single_extruder_multi_material");
if (is_SEMM && m_extruders_count > 1 && boost::starts_with(opt_key, "nozzle_diameter"))
bool independent_nozzles = m_preset_bundle && m_preset_bundle->is_bbl_vendor() && m_extruders_count > 1;
if (is_SEMM && m_extruders_count > 1 && !independent_nozzles && boost::starts_with(opt_key, "nozzle_diameter"))
{
SuppressBackgroundProcessingUpdate sbpu;
const double new_nd = boost::any_cast<double>(value);