diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index 9c280dee69..481eee6d4c 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -24,6 +24,7 @@ #include #include +#include #include "Field.hpp" #include "format.hpp" #include "NotificationManager.hpp" @@ -2394,22 +2395,42 @@ void Control::edit_extruder_sequence() m_ticks.erase_all_ticks_with_code(ToolChange); + const int extr_cnt = m_extruders_sequence.extruders.size(); + if (extr_cnt == 1) + return; + int tick = 0; double value = 0.0; - int extruder = 0; - const int extr_cnt = m_extruders_sequence.extruders.size(); + int extruder = -1; + + std::random_device rd; //Will be used to obtain a seed for the random number engine + std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd() + std::uniform_int_distribution<> distrib(0, extr_cnt-1); while (tick <= m_max_value) { + bool color_repetition = false; + if (m_extruders_sequence.random_sequence) { + int rand_extr = distrib(gen); + if (m_extruders_sequence.color_repetition) + color_repetition = rand_extr == extruder; + else + while (rand_extr == extruder) + rand_extr = distrib(gen); + extruder = rand_extr; + } + else { + extruder++; + if (extruder == extr_cnt) + extruder = 0; + } + const int cur_extruder = m_extruders_sequence.extruders[extruder]; bool meaningless_tick = tick == 0.0 && cur_extruder == extruder; - if (!meaningless_tick) + if (!meaningless_tick && !color_repetition) m_ticks.ticks.emplace(TickCode{tick, ToolChange,cur_extruder + 1, m_extruder_colors[cur_extruder]}); - extruder++; - if (extruder == extr_cnt) - extruder = 0; if (m_extruders_sequence.is_mm_intervals) { value += m_extruders_sequence.interval_by_mm; tick = get_tick_from_value(value, true); diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index c1766f83d4..4c7c3e1bb0 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -146,6 +146,8 @@ struct ExtrudersSequence bool is_mm_intervals = true; double interval_by_mm = 3.0; int interval_by_layers = 10; + bool random_sequence { true }; + bool color_repetition { false }; std::vector extruders = { 0 }; bool operator==(const ExtrudersSequence& other) const @@ -153,19 +155,23 @@ struct ExtrudersSequence return (other.is_mm_intervals == this->is_mm_intervals ) && (other.interval_by_mm == this->interval_by_mm ) && (other.interval_by_layers == this->interval_by_layers ) && + (other.random_sequence == this->random_sequence ) && + (other.color_repetition == this->color_repetition ) && (other.extruders == this->extruders ) ; } bool operator!=(const ExtrudersSequence& other) const { - return (other.is_mm_intervals != this->is_mm_intervals ) && - (other.interval_by_mm != this->interval_by_mm ) && - (other.interval_by_layers != this->interval_by_layers ) && + return (other.is_mm_intervals != this->is_mm_intervals ) || + (other.interval_by_mm != this->interval_by_mm ) || + (other.interval_by_layers != this->interval_by_layers ) || + (other.random_sequence != this->random_sequence ) || + (other.color_repetition != this->color_repetition ) || (other.extruders != this->extruders ) ; } - void add_extruder(size_t pos) + void add_extruder(size_t pos, size_t extruder_id = size_t(0)) { - extruders.insert(extruders.begin() + pos+1, size_t(0)); + extruders.insert(extruders.begin() + pos+1, extruder_id); } void delete_extruder(size_t pos) diff --git a/src/slic3r/GUI/ExtruderSequenceDialog.cpp b/src/slic3r/GUI/ExtruderSequenceDialog.cpp index 8ae5e9f32d..4099d62c7a 100644 --- a/src/slic3r/GUI/ExtruderSequenceDialog.cpp +++ b/src/slic3r/GUI/ExtruderSequenceDialog.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -138,6 +139,18 @@ ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequ intervals_box_sizer->Add(m_intervals_grid_sizer, 0, wxLEFT, em); option_sizer->Add(intervals_box_sizer, 0, wxEXPAND); + m_random_sequence = new wxCheckBox(this, wxID_ANY, "Random sequence"); + m_random_sequence->SetValue(m_sequence.random_sequence); + m_random_sequence->SetToolTip(_L("If enabled, random sequence of the selected extruders will be used.")); + m_random_sequence->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& e) { + m_sequence.random_sequence = e.IsChecked(); + m_color_repetition->Enable(m_sequence.random_sequence); + }); + + m_color_repetition = new wxCheckBox(this, wxID_ANY, "Allow next color repetition"); + m_color_repetition->SetValue(m_sequence.color_repetition); + m_color_repetition->SetToolTip(_L("If enabled, a repetition of the next random color will be allowed.")); + m_color_repetition->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& e) {m_sequence.color_repetition = e.IsChecked(); }); auto extruders_box = new wxStaticBox(this, wxID_ANY, _(L("Set extruder(tool) sequence"))+ ": "); auto extruders_box_sizer = new wxStaticBoxSizer(extruders_box, wxVERTICAL); @@ -147,6 +160,8 @@ ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequ apply_extruder_sequence(); extruders_box_sizer->Add(m_extruders_grid_sizer, 0, wxALL, em); + extruders_box_sizer->Add(m_random_sequence, 0, wxLEFT | wxBOTTOM, em); + extruders_box_sizer->Add(m_color_repetition, 0, wxLEFT | wxBOTTOM, em); option_sizer->Add(extruders_box_sizer, 0, wxEXPAND | wxTOP, em); main_sizer->Add(option_sizer, 0, wxEXPAND | wxALL, em); @@ -197,8 +212,11 @@ void ExtruderSequenceDialog::apply_extruder_sequence() auto add_btn = new ScalableButton(this, wxID_ANY, m_bmp_add); add_btn->SetToolTip(_(L("Add extruder to sequence"))); - add_btn->Bind(wxEVT_BUTTON, [this, extruder](wxEvent&) { - m_sequence.add_extruder(extruder); + add_btn->Bind(wxEVT_BUTTON, [this, extruder, extruder_selector](wxEvent&) { + size_t extr_cnt = (size_t)extruder_selector->GetCount(); + size_t seq_extr_cnt = m_sequence.extruders.size(); + size_t extr_id = seq_extr_cnt - size_t(seq_extr_cnt / extr_cnt) * extr_cnt; + m_sequence.add_extruder(extruder, std::min(extr_id, extr_cnt-1)); apply_extruder_sequence(); }); @@ -208,6 +226,10 @@ void ExtruderSequenceDialog::apply_extruder_sequence() } m_extruders_grid_sizer->ShowItems(true); // show items hidden in apply_extruder_selector() + bool show_checkboxes = m_sequence.extruders.size() > 1; + m_random_sequence->Enable(show_checkboxes); + m_color_repetition->Enable(show_checkboxes && m_sequence.random_sequence); + Fit(); Refresh(); } diff --git a/src/slic3r/GUI/ExtruderSequenceDialog.hpp b/src/slic3r/GUI/ExtruderSequenceDialog.hpp index 97d57ef120..da19f79075 100644 --- a/src/slic3r/GUI/ExtruderSequenceDialog.hpp +++ b/src/slic3r/GUI/ExtruderSequenceDialog.hpp @@ -6,6 +6,7 @@ class wxTextCtrl; class wxFlexGridSizer; +class wxCheckBox; namespace Slic3r { namespace GUI { @@ -22,6 +23,8 @@ class ExtruderSequenceDialog: public DPIDialog wxTextCtrl* m_interval_by_layers {nullptr}; wxTextCtrl* m_interval_by_mm {nullptr}; + wxCheckBox* m_random_sequence {nullptr}; + wxCheckBox* m_color_repetition{nullptr}; wxFlexGridSizer* m_intervals_grid_sizer {nullptr}; wxFlexGridSizer* m_extruders_grid_sizer {nullptr};