diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index e3f8f53b31..5a53f4ca8d 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -1372,7 +1372,7 @@ static std::vector s_Preset_filament_options {/*"filament_colour", "filament_ramming_travel_time", "filament_ramming_travel_time_nc", "filament_pre_cooling_temperature", "filament_pre_cooling_temperature_nc", "filament_preheat_temperature_delta", "filament_retract_length_nc", - "filament_change_length_nc", "filament_prime_volume_nc", + "filament_change_length_nc", "filament_prime_volume", "filament_prime_volume_nc", "long_retractions_when_ec", "retraction_distances_when_ec", //ams chamber "filament_dev_ams_drying_ams_limitations", "filament_dev_ams_drying_temperature", "filament_dev_ams_drying_time", "filament_dev_ams_drying_heat_distortion_temperature", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 0c65f5dcd5..b20374cc30 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -3975,14 +3975,27 @@ void Print::_make_wipe_tower() multi_extruder_flush.emplace_back(wipe_volumes); } - std::vectorfilament_maps = get_filament_maps(); + // Reference to BBS: BambuStudio/src/libslic3r/Print.cpp _make_wipe_tower() + // Use NozzleStatusRecorder for per-carousel-slot tracking (BBS pattern). + // The original Orca code tracked per-extruder (2 slots), which collapsed all + // carousel filaments into one slot and caused massive redundant AMS flushing. + auto group_result = get_layered_nozzle_group_result(); + MultiNozzleUtils::NozzleStatusRecorder nozzle_recorder; + + std::vectorfilament_maps = get_filament_maps(); + int layer_idx = -1; - std::vector nozzle_cur_filament_ids(nozzle_nums, -1); unsigned int current_filament_id = m_wipe_tower_data.tool_ordering.first_extruder(); - size_t cur_nozzle_id = filament_maps[current_filament_id] - 1; - nozzle_cur_filament_ids[cur_nozzle_id] = current_filament_id; + // Initialize NozzleStatusRecorder with the first filament's carousel slot + if (group_result) { + auto nozzle = group_result->get_nozzle_for_filament(current_filament_id, layer_idx); + if (nozzle) + nozzle_recorder.set_nozzle_status(nozzle->group_id, current_filament_id, nozzle->extruder_id); + } for (auto& layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { // for all layers + ++layer_idx; + if (!layer_tools.has_wipe_tower) continue; bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front(); wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height, current_filament_id, current_filament_id); @@ -3993,30 +4006,73 @@ void Print::_make_wipe_tower() if (filament_id == current_filament_id) continue; - int nozzle_id = filament_maps[filament_id] - 1; - unsigned int pre_filament_id = nozzle_cur_filament_ids[nozzle_id]; - float volume_to_purge = 0; - if (pre_filament_id != (unsigned int)(-1) && pre_filament_id != filament_id) { - volume_to_purge = multi_extruder_flush[nozzle_id][pre_filament_id][filament_id]; - // Fast purge mode uses flush_multiplier_fast; Default is inert. - float flush_multiplier = (m_config.prime_volume_mode == PrimeVolumeMode::pvmFast) ? m_config.flush_multiplier_fast.get_at(nozzle_id) - : m_config.flush_multiplier.get_at(nozzle_id); + + // Reference to BBS: BambuStudio/src/libslic3r/Print.cpp L3361-3392 + // Per-carousel-slot purge tracking via NozzleStatusRecorder + if (group_result) { + auto nozzle_info = group_result->get_nozzle_for_filament(filament_id, layer_idx); + if (nozzle_info) { + int extruder_id = nozzle_info->extruder_id; + int nozzle_id = nozzle_info->group_id; + int prev_nozzle_filament = nozzle_recorder.get_filament_in_nozzle(nozzle_id); + + if (!nozzle_recorder.is_nozzle_empty(nozzle_id) && + static_cast(filament_id) != prev_nozzle_filament) { + volume_to_purge = multi_extruder_flush[extruder_id][prev_nozzle_filament][filament_id]; + // Fast purge mode uses flush_multiplier_fast; Default is inert. + float flush_multiplier = (m_config.prime_volume_mode == PrimeVolumeMode::pvmFast) + ? m_config.flush_multiplier_fast.get_at(extruder_id) + : m_config.flush_multiplier.get_at(extruder_id); + volume_to_purge *= flush_multiplier; + volume_to_purge = layer_tools.wiping_extrusions().mark_wiping_extrusions( + *this, current_filament_id, filament_id, volume_to_purge); + } + nozzle_recorder.set_nozzle_status(nozzle_id, filament_id, extruder_id); + } + } else { + // Fallback: original Orca per-extruder path (non-carousel printers) + int nozzle_id = filament_maps[filament_id] - 1; + volume_to_purge = multi_extruder_flush[nozzle_id][current_filament_id][filament_id]; + float flush_multiplier = (m_config.prime_volume_mode == PrimeVolumeMode::pvmFast) + ? m_config.flush_multiplier_fast.get_at(nozzle_id) + : m_config.flush_multiplier.get_at(nozzle_id); volume_to_purge *= flush_multiplier; - volume_to_purge = pre_filament_id == -1 ? 0 : - layer_tools.wiping_extrusions().mark_wiping_extrusions(*this, current_filament_id, filament_id, volume_to_purge); + volume_to_purge = layer_tools.wiping_extrusions().mark_wiping_extrusions( + *this, current_filament_id, filament_id, volume_to_purge); } //During the filament change, the extruder will extrude an extra length of grab_length for the corresponding detection, so the purge can reduce this length. - float grab_purge_volume = m_config.grab_length.get_at(nozzle_id) * 2.4; //(diameter/2)^2*PI=2.4 + int grab_extruder_id = filament_maps[filament_id] - 1; + float grab_purge_volume = m_config.grab_length.get_at(grab_extruder_id) * 2.4; //(diameter/2)^2*PI=2.4 volume_to_purge = std::max(0.f, volume_to_purge - grab_purge_volume); - // Saving mode reduces the prime volume to 15 mm3; Default is inert. - float prime_volume = (m_config.prime_volume_mode == PrimeVolumeMode::pvmSaving) ? 15.f : (float) m_config.prime_volume; + // Reference to BBS: BambuStudio/src/libslic3r/Print.cpp L3381-3387 + // Select prime volume per-filament: nozzle change (carousel rotation) uses + // filament_prime_volume_nc, filament change (same nozzle slot) uses filament_prime_volume. + // BBS passes both to plan_toolchange (7 args), we select the right one here (6 args). + float wipe_volume_ec = filament_id < m_config.filament_prime_volume.values.size() + ? m_config.filament_prime_volume.values[filament_id] + : (float) m_config.prime_volume; + float wipe_volume_nc = filament_id < m_config.filament_prime_volume_nc.values.size() + ? m_config.filament_prime_volume_nc.values[filament_id] + : (float) m_config.prime_volume; + + float prime_volume = wipe_volume_ec; + if (group_result) { + bool is_nozzle_change = group_result->are_filaments_same_extruder(current_filament_id, filament_id, layer_idx) && + !group_result->are_filaments_same_nozzle(current_filament_id, filament_id, layer_idx); + if (is_nozzle_change) { + prime_volume = wipe_volume_nc; + } + } + if (m_config.prime_volume_mode == PrimeVolumeMode::pvmSaving) { + prime_volume = 15.f; + } + wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height, current_filament_id, filament_id, prime_volume, volume_to_purge); current_filament_id = filament_id; - nozzle_cur_filament_ids[nozzle_id] = filament_id; } layer_tools.wiping_extrusions().ensure_perimeters_infills_order(*this); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index e92562e132..a3f301bd32 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -7995,6 +7995,15 @@ void PrintConfigDef::init_fff_params() def->mode = comDevelop; def->set_default_value(new ConfigOptionBool(false)); + // Reference to BBS: BambuStudio/src/libslic3r/PrintConfig.cpp L2617-2624 + def = this->add("filament_prime_volume", coFloats); + def->label = L("Filament change"); + def->tooltip = L("The volume of material required to prime the extruder on the tower, excluding a hotend change."); + def->sidetext = L("mm³"); + def->min = 1.0; + def->mode = comSimple; + def->set_default_value(new ConfigOptionFloats{45.}); + def = this->add("filament_prime_volume_nc", coFloats); def->label = L("Hotend change"); def->tooltip = L("The volume of material required to prime the extruder for a hotend change on the tower."); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index f9aab25f2f..902484be8f 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1837,6 +1837,8 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( // BBS: wipe tower is only used for priming ((ConfigOptionFloat, prime_volume)) // Nozzle-change (nc) prime volume + pre-heat delta + // Reference to BBS: BambuStudio/src/libslic3r/PrintConfig.hpp L1524-1525 + ((ConfigOptionFloats, filament_prime_volume)) ((ConfigOptionFloats, filament_prime_volume_nc)) ((ConfigOptionFloatsNullable, filament_preheat_temperature_delta)) ((ConfigOptionFloats, flush_multiplier)) diff --git a/tests/_orca-test-repo b/tests/_orca-test-repo new file mode 160000 index 0000000000..0dfd8df467 --- /dev/null +++ b/tests/_orca-test-repo @@ -0,0 +1 @@ +Subproject commit 0dfd8df467895d7093d50b267c7209fd53f43a40