feat(libslic3r): multi-nozzle slicing engine for H2C/A2L

Port BambuStudio's dual-nozzle slicing core: H2C-era config keys, filament-to-nozzle grouping with per-layer dynamic regrouping, filament/nozzle/hotend gcode placeholder vocabulary, multi-nozzle wipe tower pre-heat/pre-cool, the two-pass pre-cooling injector, and corexy farthest-point timelapse.
This commit is contained in:
SoftFever
2026-07-09 00:06:26 +08:00
parent 781ecdc2c1
commit 237ef41b06
36 changed files with 7622 additions and 708 deletions

View File

@@ -52,6 +52,9 @@ static std::vector<std::string> s_project_options {
"wipe_tower_rotation_angle",
"curr_bed_type",
"flush_multiplier",
// Fast-purge mode: project-level purge control, inert at Default.
"flush_multiplier_fast",
"prime_volume_mode",
"nozzle_volume_type",
"filament_map_mode",
"filament_map"
@@ -348,7 +351,7 @@ PresetBundle::PresetBundle()
auto& default_config = this->filaments.default_preset().config;
for(const std::string& opt_key : default_config.keys()){
ConfigOption* opt = default_config.optptr(opt_key, false);
bool is_override_key = std::find(filament_extruder_override_keys.begin(),filament_extruder_override_keys.end(), opt_key) != filament_extruder_override_keys.end();
bool is_override_key = is_filament_extruder_override_key(opt_key);
if(!is_override_key || !opt->nullable())
continue;
opt->deserialize("nil",ForwardCompatibilitySubstitutionRule::Disable);
@@ -721,6 +724,8 @@ std::optional<FilamentBaseInfo> PresetBundle::get_filament_by_filament_id(const
auto iter = std::find(compatible_printers.begin(), compatible_printers.end(), printer_name);
if (iter != compatible_printers.end() && config.has("filament_printable")) {
info.filament_printable = config.option<ConfigOptionInts>("filament_printable")->values[0];
if (config.has("filament_extruder_compatibility"))
info.set_filament_extruder_compatibility(config.option<ConfigOptionInts>("filament_extruder_compatibility")->values[0]);
return info;
}
}
@@ -3872,10 +3877,46 @@ DynamicPrintConfig PresetBundle::full_config_secure(std::optional<std::vector<in
config.erase("printhost_cafile");
config.erase("printhost_user");
config.erase("printhost_password");
config.erase("printhost_port");
config.erase("printhost_port");
return config;
}
std::vector<std::vector<std::vector<float>>> PresetBundle::get_full_flush_matrix(bool with_multiplier) const
{
auto full_config = this->full_config();
int extruder_nums = full_config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
std::vector<double> flush_volume_value = full_config.option<ConfigOptionFloats>("flush_volumes_matrix")->values;
int filament_nums = full_config.option<ConfigOptionStrings>("filament_type")->values.size();
std::vector<std::vector<std::vector<float>>> matrix;
for (size_t extruder_id = 0; extruder_id < extruder_nums; ++extruder_id) {
std::vector<float> flush_matrix(cast<float>(get_flush_volumes_matrix(flush_volume_value, extruder_id, extruder_nums)));
std::vector<std::vector<float>> wipe_volumes;
for (unsigned int i = 0; i < filament_nums; ++i)
wipe_volumes.push_back(std::vector<float>(flush_matrix.begin() + i * filament_nums, flush_matrix.begin() + (i + 1) * filament_nums));
matrix.emplace_back(wipe_volumes);
}
if (with_multiplier) {
// Fast purge mode uses flush_multiplier_fast; the default prime_volume_mode==Default
// (or the key absent) reads flush_multiplier, so this is inert.
auto* mode_opt = project_config.option<ConfigOptionEnum<PrimeVolumeMode>>("prime_volume_mode");
const bool use_fast = mode_opt && mode_opt->value == PrimeVolumeMode::pvmFast;
auto* mult_opt = project_config.option<ConfigOptionFloats>(use_fast ? "flush_multiplier_fast" : "flush_multiplier");
auto flush_multiplies = mult_opt ? mult_opt->values : project_config.option<ConfigOptionFloats>("flush_multiplier")->values;
flush_multiplies.resize(extruder_nums, 1);
for (size_t extruder_id = 0; extruder_id < extruder_nums; ++extruder_id) {
for (auto& vec : matrix[extruder_id]) {
for (auto& v : vec)
v *= flush_multiplies[extruder_id];
}
}
}
return matrix;
}
const std::set<std::string> ignore_settings_list ={
"inherits",
"print_settings_id", "filament_settings_id", "printer_settings_id"
@@ -4770,6 +4811,8 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
model.use_double_extruder_default_texture = it.value();
} else if (boost::iequals(it.key(), BBL_JSON_KEY_BOTTOM_TEXTURE_RECT)) {
model.bottom_texture_rect = it.value();
} else if (boost::iequals(it.key(), BBL_JSON_KEY_BOTTOM_TEXTURE_RECT_LONGER)) {
model.bottom_texture_rect_longer = it.value();
} else if (boost::iequals(it.key(), BBL_JSON_KEY_MIDDLE_TEXTURE_RECT)) {
model.middle_texture_rect = it.value();
}