mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-27 21:02:23 +00:00
Add toolchange ordering option (Standard/Cyclic). (#13582)
This commit is contained in:
@@ -187,6 +187,10 @@ static void apply_first_layer_order(const DynamicPrintConfig* config, std::vecto
|
|||||||
|
|
||||||
void ToolOrdering::handle_dontcare_extruder(const std::vector<unsigned int>& tool_order_layer0)
|
void ToolOrdering::handle_dontcare_extruder(const std::vector<unsigned int>& tool_order_layer0)
|
||||||
{
|
{
|
||||||
|
const PrintConfig* print_config = m_print_config_ptr;
|
||||||
|
if (!print_config && m_print_object_ptr)
|
||||||
|
print_config = &m_print_object_ptr->print()->config();
|
||||||
|
|
||||||
if(m_layer_tools.empty() || tool_order_layer0.empty())
|
if(m_layer_tools.empty() || tool_order_layer0.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -221,6 +225,8 @@ void ToolOrdering::handle_dontcare_extruder(const std::vector<unsigned int>& too
|
|||||||
for (int i = 1; i < m_layer_tools.size(); i++) {
|
for (int i = 1; i < m_layer_tools.size(); i++) {
|
||||||
LayerTools& lt = m_layer_tools[i];
|
LayerTools& lt = m_layer_tools[i];
|
||||||
|
|
||||||
|
// Extruders in lt.extruders are already sorted.
|
||||||
|
|
||||||
if (lt.extruders.empty())
|
if (lt.extruders.empty())
|
||||||
continue;
|
continue;
|
||||||
if (lt.extruders.size() == 1 && lt.extruders.front() == 0)
|
if (lt.extruders.size() == 1 && lt.extruders.front() == 0)
|
||||||
@@ -229,14 +235,23 @@ void ToolOrdering::handle_dontcare_extruder(const std::vector<unsigned int>& too
|
|||||||
if (lt.extruders.front() == 0)
|
if (lt.extruders.front() == 0)
|
||||||
// Pop the "don't care" extruder, the "don't care" region will be merged with the next one.
|
// Pop the "don't care" extruder, the "don't care" region will be merged with the next one.
|
||||||
lt.extruders.erase(lt.extruders.begin());
|
lt.extruders.erase(lt.extruders.begin());
|
||||||
// Reorder the extruders to start with the last one.
|
|
||||||
for (size_t i = 1; i < lt.extruders.size(); ++i)
|
if (print_config == nullptr
|
||||||
if (lt.extruders[i] == last_extruder_id) {
|
|| print_config->toolchange_ordering == ToolChangeOrderingType::Default)
|
||||||
// Move the last extruder to the front.
|
{
|
||||||
memmove(lt.extruders.data() + 1, lt.extruders.data(), i * sizeof(unsigned int));
|
// Reorder the extruders to start with the last one.
|
||||||
lt.extruders.front() = last_extruder_id;
|
for (size_t i = 1; i < lt.extruders.size(); ++i) {
|
||||||
break;
|
if (lt.extruders[i] == last_extruder_id) {
|
||||||
|
// Move the last extruder to the front.
|
||||||
|
std::rotate(
|
||||||
|
lt.extruders.begin(),
|
||||||
|
lt.extruders.begin() + i,
|
||||||
|
lt.extruders.begin() + i + 1
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
last_extruder_id = lt.extruders.back();
|
last_extruder_id = lt.extruders.back();
|
||||||
}
|
}
|
||||||
@@ -252,6 +267,10 @@ void ToolOrdering::handle_dontcare_extruder(const std::vector<unsigned int>& too
|
|||||||
|
|
||||||
void ToolOrdering::handle_dontcare_extruder(unsigned int last_extruder_id)
|
void ToolOrdering::handle_dontcare_extruder(unsigned int last_extruder_id)
|
||||||
{
|
{
|
||||||
|
const PrintConfig* print_config = m_print_config_ptr;
|
||||||
|
if (!print_config && m_print_object_ptr)
|
||||||
|
print_config = &m_print_object_ptr->print()->config();
|
||||||
|
|
||||||
if(m_layer_tools.empty())
|
if(m_layer_tools.empty())
|
||||||
return;
|
return;
|
||||||
if(last_extruder_id == (unsigned int)-1){
|
if(last_extruder_id == (unsigned int)-1){
|
||||||
@@ -275,6 +294,8 @@ void ToolOrdering::handle_dontcare_extruder(unsigned int last_extruder_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (LayerTools < : m_layer_tools) {
|
for (LayerTools < : m_layer_tools) {
|
||||||
|
// Extruders in lt.extruders are already sorted.
|
||||||
|
|
||||||
if (lt.extruders.empty())
|
if (lt.extruders.empty())
|
||||||
continue;
|
continue;
|
||||||
if (lt.extruders.size() == 1 && lt.extruders.front() == 0)
|
if (lt.extruders.size() == 1 && lt.extruders.front() == 0)
|
||||||
@@ -283,21 +304,30 @@ void ToolOrdering::handle_dontcare_extruder(unsigned int last_extruder_id)
|
|||||||
if (lt.extruders.front() == 0)
|
if (lt.extruders.front() == 0)
|
||||||
// Pop the "don't care" extruder, the "don't care" region will be merged with the next one.
|
// Pop the "don't care" extruder, the "don't care" region will be merged with the next one.
|
||||||
lt.extruders.erase(lt.extruders.begin());
|
lt.extruders.erase(lt.extruders.begin());
|
||||||
// Reorder the extruders to start with the last one.
|
|
||||||
for (size_t i = 1; i < lt.extruders.size(); ++ i)
|
if (print_config == nullptr
|
||||||
if (lt.extruders[i] == last_extruder_id) {
|
|| print_config->toolchange_ordering == ToolChangeOrderingType::Default)
|
||||||
// Move the last extruder to the front.
|
{
|
||||||
memmove(lt.extruders.data() + 1, lt.extruders.data(), i * sizeof(unsigned int));
|
// Reorder the extruders to start with the last one.
|
||||||
lt.extruders.front() = last_extruder_id;
|
for (size_t i = 1; i < lt.extruders.size(); ++i) {
|
||||||
break;
|
if (lt.extruders[i] == last_extruder_id) {
|
||||||
|
// Move the last extruder to the front.
|
||||||
|
std::rotate(
|
||||||
|
lt.extruders.begin(),
|
||||||
|
lt.extruders.begin() + i,
|
||||||
|
lt.extruders.begin() + i + 1
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (lt == m_layer_tools[0]) {
|
if (lt == m_layer_tools[0]) {
|
||||||
// On first layer with wipe tower, prefer a soluble extruder
|
// On first layer with wipe tower, prefer a soluble extruder
|
||||||
// at the beginning, so it is not wiped on the first layer.
|
// at the beginning, so it is not wiped on the first layer.
|
||||||
if (m_print_config_ptr && m_print_config_ptr->enable_prime_tower) {
|
if (print_config && print_config->enable_prime_tower) {
|
||||||
for (size_t i = 0; i<lt.extruders.size(); ++i)
|
for (size_t i = 0; i<lt.extruders.size(); ++i)
|
||||||
if (m_print_config_ptr->filament_soluble.get_at(lt.extruders[i]-1)) { // 1-based...
|
if (print_config->filament_soluble.get_at(lt.extruders[i]-1)) { // 1-based...
|
||||||
std::swap(lt.extruders[i], lt.extruders.front());
|
std::swap(lt.extruders[i], lt.extruders.front());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -396,6 +426,7 @@ void ToolOrdering::sort_and_build_data(const PrintObject& object , unsigned int
|
|||||||
ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material)
|
ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material)
|
||||||
{
|
{
|
||||||
m_print_full_config = &object.print()->full_print_config();
|
m_print_full_config = &object.print()->full_print_config();
|
||||||
|
m_print_config_ptr = &object.print()->config();
|
||||||
m_print_object_ptr = &object;
|
m_print_object_ptr = &object;
|
||||||
m_print = const_cast<Print*>(object.print());
|
m_print = const_cast<Print*>(object.print());
|
||||||
if (object.layers().empty())
|
if (object.layers().empty())
|
||||||
@@ -1329,8 +1360,11 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first
|
|||||||
if (!m_layer_tools.empty())
|
if (!m_layer_tools.empty())
|
||||||
first_layer_filaments = m_layer_tools[0].extruders;
|
first_layer_filaments = m_layer_tools[0].extruders;
|
||||||
|
|
||||||
|
const bool use_cyclic_ordering =
|
||||||
|
(print_config->toolchange_ordering == ToolChangeOrderingType::Cyclic);
|
||||||
|
|
||||||
// other_layers_seq: the layer_idx and extruder_idx are base on 1
|
// other_layers_seq: the layer_idx and extruder_idx are base on 1
|
||||||
auto get_custom_seq = [&other_layers_seqs, &reorder_first_layer, &first_layer_filaments](int layer_idx, std::vector<int>& out_seq) -> bool {
|
auto get_custom_seq = [&other_layers_seqs, &reorder_first_layer, &first_layer_filaments, &layer_filaments, use_cyclic_ordering](int layer_idx, std::vector<int>& out_seq) -> bool {
|
||||||
if (!reorder_first_layer && layer_idx == 0) {
|
if (!reorder_first_layer && layer_idx == 0) {
|
||||||
out_seq.resize(first_layer_filaments.size());
|
out_seq.resize(first_layer_filaments.size());
|
||||||
std::transform(first_layer_filaments.begin(), first_layer_filaments.end(), out_seq.begin(), [](auto item) {return item + 1; });
|
std::transform(first_layer_filaments.begin(), first_layer_filaments.end(), out_seq.begin(), [](auto item) {return item + 1; });
|
||||||
@@ -1343,6 +1377,15 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_cyclic_ordering && layer_idx >= 0 && size_t(layer_idx) < layer_filaments.size()) {
|
||||||
|
std::vector<unsigned int> ordered = layer_filaments[size_t(layer_idx)];
|
||||||
|
std::sort(ordered.begin(), ordered.end());
|
||||||
|
out_seq.resize(ordered.size());
|
||||||
|
std::transform(ordered.begin(), ordered.end(), out_seq.begin(), [](auto item) { return int(item) + 1; });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1272,6 +1272,7 @@ static std::vector<std::string> s_Preset_print_options{
|
|||||||
"wipe_tower_bridging",
|
"wipe_tower_bridging",
|
||||||
"wipe_tower_extra_flow",
|
"wipe_tower_extra_flow",
|
||||||
"single_extruder_multi_material_priming",
|
"single_extruder_multi_material_priming",
|
||||||
|
"toolchange_ordering",
|
||||||
"wipe_tower_rotation_angle",
|
"wipe_tower_rotation_angle",
|
||||||
"tree_support_branch_distance_organic",
|
"tree_support_branch_distance_organic",
|
||||||
"tree_support_branch_diameter_organic",
|
"tree_support_branch_diameter_organic",
|
||||||
|
|||||||
@@ -330,6 +330,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||||||
|| opt_key == "first_layer_print_sequence"
|
|| opt_key == "first_layer_print_sequence"
|
||||||
|| opt_key == "other_layers_print_sequence"
|
|| opt_key == "other_layers_print_sequence"
|
||||||
|| opt_key == "other_layers_print_sequence_nums"
|
|| opt_key == "other_layers_print_sequence_nums"
|
||||||
|
|| opt_key == "toolchange_ordering"
|
||||||
|| opt_key == "extruder_ams_count"
|
|| opt_key == "extruder_ams_count"
|
||||||
|| opt_key == "filament_map_mode"
|
|| opt_key == "filament_map_mode"
|
||||||
|| opt_key == "filament_map"
|
|| opt_key == "filament_map"
|
||||||
|
|||||||
@@ -522,6 +522,12 @@ static t_config_enum_values s_keys_map_PerimeterGeneratorType{
|
|||||||
};
|
};
|
||||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PerimeterGeneratorType)
|
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PerimeterGeneratorType)
|
||||||
|
|
||||||
|
static t_config_enum_values s_keys_map_ToolChangeOrderingType {
|
||||||
|
{ "default", int(ToolChangeOrderingType::Default) },
|
||||||
|
{ "cyclic", int(ToolChangeOrderingType::Cyclic) }
|
||||||
|
};
|
||||||
|
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(ToolChangeOrderingType)
|
||||||
|
|
||||||
static const t_config_enum_values s_keys_map_ZHopType = {
|
static const t_config_enum_values s_keys_map_ZHopType = {
|
||||||
{ "Auto Lift", zhtAuto },
|
{ "Auto Lift", zhtAuto },
|
||||||
{ "Normal Lift", zhtNormal },
|
{ "Normal Lift", zhtNormal },
|
||||||
@@ -6076,6 +6082,22 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
|
def = this->add("toolchange_ordering", coEnum);
|
||||||
|
def->label = L("Toolchange ordering");
|
||||||
|
def->category = L("Advanced");
|
||||||
|
def->tooltip = L(
|
||||||
|
"Determines the order of tool changes on each layer.\n"
|
||||||
|
"- Default: Starts with the last used extruder to minimize tool changes.\n"
|
||||||
|
"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool."
|
||||||
|
);
|
||||||
|
def->mode = comAdvanced;
|
||||||
|
def->enum_keys_map = &ConfigOptionEnum<ToolChangeOrderingType>::get_enum_values();
|
||||||
|
def->enum_values.emplace_back("default");
|
||||||
|
def->enum_values.emplace_back("cyclic");
|
||||||
|
def->enum_labels.emplace_back(L("Default"));
|
||||||
|
def->enum_labels.emplace_back(L("Cyclic"));
|
||||||
|
def->set_default_value(new ConfigOptionEnum<ToolChangeOrderingType>(ToolChangeOrderingType::Default));
|
||||||
|
|
||||||
def = this->add("slice_closing_radius", coFloat);
|
def = this->add("slice_closing_radius", coFloat);
|
||||||
def->label = L("Slice gap closing radius");
|
def->label = L("Slice gap closing radius");
|
||||||
def->category = L("Quality");
|
def->category = L("Quality");
|
||||||
|
|||||||
@@ -300,6 +300,12 @@ enum class PerimeterGeneratorType
|
|||||||
Arachne
|
Arachne
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ToolChangeOrderingType
|
||||||
|
{
|
||||||
|
Default,
|
||||||
|
Cyclic,
|
||||||
|
};
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
enum OverhangFanThreshold {
|
enum OverhangFanThreshold {
|
||||||
Overhang_threshold_none = 0,
|
Overhang_threshold_none = 0,
|
||||||
@@ -561,6 +567,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrintHostType)
|
|||||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType)
|
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType)
|
||||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(WipeTowerWallType)
|
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(WipeTowerWallType)
|
||||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PerimeterGeneratorType)
|
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PerimeterGeneratorType)
|
||||||
|
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ToolChangeOrderingType)
|
||||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PowerLossRecoveryMode)
|
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PowerLossRecoveryMode)
|
||||||
|
|
||||||
#undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS
|
#undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS
|
||||||
@@ -1413,6 +1420,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||||||
((ConfigOptionBool, single_extruder_multi_material))
|
((ConfigOptionBool, single_extruder_multi_material))
|
||||||
((ConfigOptionBool, manual_filament_change))
|
((ConfigOptionBool, manual_filament_change))
|
||||||
((ConfigOptionBool, single_extruder_multi_material_priming))
|
((ConfigOptionBool, single_extruder_multi_material_priming))
|
||||||
|
((ConfigOptionEnum<ToolChangeOrderingType>, toolchange_ordering))
|
||||||
((ConfigOptionBool, wipe_tower_no_sparse_layers))
|
((ConfigOptionBool, wipe_tower_no_sparse_layers))
|
||||||
((ConfigOptionString, change_filament_gcode))
|
((ConfigOptionString, change_filament_gcode))
|
||||||
((ConfigOptionString, change_extrusion_role_gcode))
|
((ConfigOptionString, change_extrusion_role_gcode))
|
||||||
|
|||||||
@@ -2976,6 +2976,7 @@ void TabPrint::build()
|
|||||||
optgroup->append_single_option_line("flush_into_support", "multimaterial_settings_flush_options#flush-into-objects-support");
|
optgroup->append_single_option_line("flush_into_support", "multimaterial_settings_flush_options#flush-into-objects-support");
|
||||||
optgroup = page->new_optgroup(L("Advanced"), L"advanced");
|
optgroup = page->new_optgroup(L("Advanced"), L"advanced");
|
||||||
optgroup->append_single_option_line("interlocking_beam", "multimaterial_settings_advanced#interlocking-beam");
|
optgroup->append_single_option_line("interlocking_beam", "multimaterial_settings_advanced#interlocking-beam");
|
||||||
|
optgroup->append_single_option_line("toolchange_ordering", "multimaterial_settings_advanced#toolchange-ordering");
|
||||||
optgroup->append_single_option_line("interface_shells", "multimaterial_settings_advanced#interface-shells");
|
optgroup->append_single_option_line("interface_shells", "multimaterial_settings_advanced#interface-shells");
|
||||||
optgroup->append_single_option_line("mmu_segmented_region_max_width", "multimaterial_settings_advanced#maximum-width-of-segmented-region");
|
optgroup->append_single_option_line("mmu_segmented_region_max_width", "multimaterial_settings_advanced#maximum-width-of-segmented-region");
|
||||||
optgroup->append_single_option_line("mmu_segmented_region_interlocking_depth", "multimaterial_settings_advanced#interlocking-depth-of-segmented-region");
|
optgroup->append_single_option_line("mmu_segmented_region_interlocking_depth", "multimaterial_settings_advanced#interlocking-depth-of-segmented-region");
|
||||||
|
|||||||
Reference in New Issue
Block a user