From ed3f0e28983a39a79154c2f762de419d20bbf64b Mon Sep 17 00:00:00 2001 From: Argo <52103738+Argolein@users.noreply.github.com> Date: Tue, 10 Feb 2026 03:56:38 +0100 Subject: [PATCH] Fix issue #10971 (#12108) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sorry had to re-create the PR as I did some chaos in my repo with CLI. xD Fixes issue https://github.com/OrcaSlicer/OrcaSlicer/issues/10971 Description: Fix wipe tower filament selection and clean up tool ordering. Added wipe_tower_filament handling to WipeTower2 (store config, mark non-selected tools as “soluble,” and use it in toolchange selection) and ensured the configured wipe‑tower extruder is included in the extruder list for ordering. Removed duplicated/merged tool‑ordering code (extra insert_wipe_tower_extruder definition, duplicate declaration, and redundant reorder block) so the tool order logic runs only once. image --- src/libslic3r/GCode/ToolOrdering.cpp | 36 ++++++++++++++++++++++++---- src/libslic3r/GCode/ToolOrdering.hpp | 1 + src/libslic3r/GCode/WipeTower.cpp | 2 +- src/libslic3r/GCode/WipeTower2.cpp | 22 ++++++++++------- src/libslic3r/GCode/WipeTower2.hpp | 1 + src/libslic3r/Print.cpp | 6 +++++ 6 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 6de65a5dd6..08e004bc30 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -306,6 +306,26 @@ void ToolOrdering::handle_dontcare_extruder(unsigned int last_extruder_id) } } +bool ToolOrdering::insert_wipe_tower_extruder() +{ + if (!m_print_config_ptr || !m_print_config_ptr->enable_prime_tower) + return false; + if (m_print_config_ptr->wipe_tower_filament == 0) + return false; + + bool changed = false; + const unsigned int wipe_extruder = (unsigned int)(m_print_config_ptr->wipe_tower_filament - 1); + for (LayerTools < : m_layer_tools) { + if (lt.wipe_tower_partitions > 0) { + if (std::find(lt.extruders.begin(), lt.extruders.end(), wipe_extruder) == lt.extruders.end()) { + lt.extruders.emplace_back(wipe_extruder); + changed = true; + } + } + } + return changed; +} + void ToolOrdering::sort_and_build_data(const Print& print, unsigned int first_extruder, bool prime_multi_material) { // if first extruder is -1, we can decide the first layer tool order before doing reorder function @@ -328,9 +348,13 @@ void ToolOrdering::sort_and_build_data(const Print& print, unsigned int first_ex max_layer_height = calc_max_layer_height(print.config(), max_layer_height); - this->collect_extruder_statistics(prime_multi_material); - this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height); + if (this->insert_wipe_tower_extruder()) { + reorder_extruders_for_minimum_flush_volume(reorder_first_layer); + this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height); + } + + this->collect_extruder_statistics(prime_multi_material); } void ToolOrdering::sort_and_build_data(const PrintObject& object , unsigned int first_extruder, bool prime_multi_material) @@ -343,9 +367,13 @@ void ToolOrdering::sort_and_build_data(const PrintObject& object , unsigned int double max_layer_height = calc_max_layer_height(object.print()->config(), object.config().layer_height); - this->collect_extruder_statistics(prime_multi_material); - this->fill_wipe_tower_partitions(object.print()->config(), object.layers().front()->print_z - object.layers().front()->height, max_layer_height); + if (this->insert_wipe_tower_extruder()) { + reorder_extruders_for_minimum_flush_volume(reorder_first_layer); + this->fill_wipe_tower_partitions(object.print()->config(), object.layers().front()->print_z - object.layers().front()->height, max_layer_height); + } + + this->collect_extruder_statistics(prime_multi_material); } diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp index 7f7fc6a6ce..7bbfa2da1f 100644 --- a/src/libslic3r/GCode/ToolOrdering.hpp +++ b/src/libslic3r/GCode/ToolOrdering.hpp @@ -258,6 +258,7 @@ private: void initialize_layers(std::vector &zs); void collect_extruders(const PrintObject &object, const std::vector> &per_layer_extruder_switches); void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_layer_height); + bool insert_wipe_tower_extruder(); void mark_skirt_layers(const PrintConfig &config, coordf_t max_layer_height); void collect_extruder_statistics(bool prime_multi_material); void reorder_extruders_for_minimum_flush_volume(bool reorder_first_layer); diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index 0be6748594..4c6ed404b5 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -1540,7 +1540,7 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config) m_filpar.push_back(FilamentParameters()); m_filpar[idx].material = config.filament_type.get_at(idx); - m_filpar[idx].is_soluble = config.filament_soluble.get_at(idx); + m_filpar[idx].is_soluble = config.wipe_tower_filament == 0 ? config.filament_soluble.get_at(idx) : (idx != size_t(config.wipe_tower_filament - 1)); // BBS m_filpar[idx].is_support = config.filament_is_support.get_at(idx); m_filpar[idx].nozzle_temperature = config.nozzle_temperature.get_at(idx); diff --git a/src/libslic3r/GCode/WipeTower2.cpp b/src/libslic3r/GCode/WipeTower2.cpp index 19e98e4a09..ba22338eba 100644 --- a/src/libslic3r/GCode/WipeTower2.cpp +++ b/src/libslic3r/GCode/WipeTower2.cpp @@ -1227,6 +1227,7 @@ WipeTower::ToolChangeResult WipeTower2::construct_tcr(WipeTowerWriter2& writer, WipeTower2::WipeTower2(const PrintConfig& config, const PrintRegionConfig& default_region_config,int plate_idx, Vec3d plate_origin, const std::vector>& wiping_matrix, size_t initial_tool) : m_semm(config.single_extruder_multi_material.value), m_enable_filament_ramming(config.enable_filament_ramming.value), + m_wipe_tower_filament(config.wipe_tower_filament.value), m_wipe_tower_pos(config.wipe_tower_x.get_at(plate_idx), config.wipe_tower_y.get_at(plate_idx)), m_wipe_tower_width(float(config.prime_tower_width)), m_wipe_tower_rotation_angle(float(config.wipe_tower_rotation_angle)), @@ -1309,7 +1310,10 @@ void WipeTower2::set_extruder(size_t idx, const PrintConfig& config) m_filpar.push_back(FilamentParameters()); m_filpar[idx].material = config.filament_type.get_at(idx); - m_filpar[idx].is_soluble = config.filament_soluble.get_at(idx); + if (m_wipe_tower_filament > 0) + m_filpar[idx].is_soluble = (idx != size_t(m_wipe_tower_filament - 1)); + else + m_filpar[idx].is_soluble = config.filament_soluble.get_at(idx); m_filpar[idx].temperature = config.nozzle_temperature.get_at(idx); m_filpar[idx].first_layer_temperature = config.nozzle_temperature_initial_layer.get_at(idx); m_filpar[idx].filament_minimal_purge_on_wipe_tower = config.filament_minimal_purge_on_wipe_tower.get_at(idx); @@ -2224,14 +2228,16 @@ void WipeTower2::save_on_last_wipe() int WipeTower2::first_toolchange_to_nonsoluble( const std::vector& tool_changes) const { - // Orca: allow calculation of the required depth and wipe volume for soluable toolchanges as well - // NOTE: it's not clear if this is the right way, technically we should disable wipe tower if soluble filament is used as it - // will will make the wipe tower unstable. Need to revist this in the future. + // If a specific wipe tower filament is forced, use it to decide where to finish the layer. + if (m_wipe_tower_filament > 0) { + for (size_t idx = 0; idx < tool_changes.size(); ++idx) { + if (!m_filpar[tool_changes[idx].new_tool].is_soluble) + return idx; + } + return -1; + } + // Orca: allow calculation of the required depth and wipe volume for soluble toolchanges as well. return tool_changes.empty() ? -1 : 0; - //for (size_t idx=0; idx Print::extruders(bool conside_custom_gcode) const } } + // If a wipe tower filament is explicitly set, ensure it participates in tool ordering. + if (has_wipe_tower() && config().wipe_tower_filament != 0 && extruders.size() > 1) { + assert(config().wipe_tower_filament > 0 && config().wipe_tower_filament < int(config().nozzle_diameter.size())); + extruders.emplace_back(config().wipe_tower_filament - 1); // config value is 1-based + } + sort_remove_duplicates(extruders); return extruders; }