From dab9a98e0d7c1b64ec9b00df7ed2acc3d1450c0a Mon Sep 17 00:00:00 2001 From: "liz.li" Date: Mon, 26 Feb 2024 15:38:23 +0800 Subject: [PATCH] NEW: support to adjust other layers print sequence Jira: 6338 Change-Id: I5e6aef71aa9e6e97c1859aaaeb9ada5f1340414a --- src/libslic3r/ParameterUtils.cpp | 4 +- src/libslic3r/PrintConfig.cpp | 19 +- src/libslic3r/PrintConfig.hpp | 2 +- src/slic3r/GUI/OptionsGroup.cpp | 5 + src/slic3r/GUI/PartPlate.cpp | 60 +++- src/slic3r/GUI/PartPlate.hpp | 3 + src/slic3r/GUI/PlateSettingsDialog.cpp | 426 +++++++++++++++++++++++-- src/slic3r/GUI/PlateSettingsDialog.hpp | 93 +++++- src/slic3r/GUI/Plater.cpp | 14 +- src/slic3r/GUI/Tab.cpp | 60 +++- 10 files changed, 639 insertions(+), 47 deletions(-) diff --git a/src/libslic3r/ParameterUtils.cpp b/src/libslic3r/ParameterUtils.cpp index c72468567..4e5fed7e6 100644 --- a/src/libslic3r/ParameterUtils.cpp +++ b/src/libslic3r/ParameterUtils.cpp @@ -15,7 +15,7 @@ std::vector get_other_layers_print_sequence(int sequence_num for (int i = 0; i < sequence_nums; ++i) { std::vector item; - item.assign(sequence.begin() + i * item_nums, sequence.begin() + ((i + 1) * item_nums - 1)); + item.assign(sequence.begin() + i * item_nums, sequence.begin() + ((i + 1) * item_nums)); assert(item.size() > 2); std::pair, std::vector> res_item; @@ -36,6 +36,8 @@ void get_other_layers_print_sequence(const std::vector &cust sequence_nums = (int) customize_sequences.size(); for (const auto &customize_sequence : customize_sequences) { + sequence.push_back(customize_sequence.first.first); + sequence.push_back(customize_sequence.first.second); sequence.insert(sequence.end(), customize_sequence.second.begin(), customize_sequence.second.end()); } } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 4550293c8..c3981c74d 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -303,11 +303,11 @@ static const t_config_enum_values s_keys_map_BedType = { CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(BedType) // BBS -static const t_config_enum_values s_keys_map_FirstLayerSeq = { +static const t_config_enum_values s_keys_map_LayerSeq = { { "Auto", flsAuto }, { "Customize", flsCutomize }, }; -CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(FirstLayerSeq) +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(LayerSeq) static t_config_enum_values s_keys_map_NozzleType { { "undefine", int(NozzleType::ntUndefine) }, @@ -673,13 +673,24 @@ void PrintConfigDef::init_fff_params() def = this->add("first_layer_sequence_choice", coEnum); def->category = L("Quality"); def->label = L("First layer filament sequence"); - def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); def->enum_values.push_back("Auto"); def->enum_values.push_back("Customize"); def->enum_labels.push_back(L("Auto")); def->enum_labels.push_back(L("Customize")); def->mode = comSimple; - def->set_default_value(new ConfigOptionEnum(flsAuto)); + def->set_default_value(new ConfigOptionEnum(flsAuto)); + + def = this->add("other_layers_sequence_choice", coEnum); + def->category = L("Quality"); + def->label = L("Other layers filament sequence"); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("Auto"); + def->enum_values.push_back("Customize"); + def->enum_labels.push_back(L("Auto")); + def->enum_labels.push_back(L("Customize")); + def->mode = comSimple; + def->set_default_value(new ConfigOptionEnum(flsAuto)); def = this->add("before_layer_change_gcode", coString); def->label = L("Before layer change G-code"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 5fa8e1964..9ce662408 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -210,7 +210,7 @@ enum BedType { }; // BBS -enum FirstLayerSeq { +enum LayerSeq { flsAuto, flsCutomize }; diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 53b003815..e2e800faa 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -1037,6 +1037,11 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config ret = 0; break; } + if (!config.has("other_layers_sequence_choice") && opt_key == "other_layers_sequence_choice") { + // reset to Auto value + ret = 0; + break; + } if (!config.has("curr_bed_type") && opt_key == "curr_bed_type") { // reset to global value DynamicConfig& global_cfg = wxGetApp().preset_bundle->project_config; diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index dc04cb290..a398f1a28 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -970,7 +970,7 @@ void PartPlate::render_icons(bool bottom, bool only_body, int hover_id) render_icon_texture(position_id, tex_coords_id, m_plate_name_edit_icon, m_partplate_list->m_plate_name_edit_texture, m_plate_name_edit_vbo_id); if (m_partplate_list->render_plate_settings) { - bool has_plate_settings = get_bed_type() != BedType::btDefault || get_print_seq() != PrintSequence::ByDefault || !get_first_layer_print_sequence().empty() || has_spiral_mode_config(); + bool has_plate_settings = get_bed_type() != BedType::btDefault || get_print_seq() != PrintSequence::ByDefault || !get_first_layer_print_sequence().empty() || !get_other_layers_print_sequence().empty() || has_spiral_mode_config(); if (hover_id == 5) { if (!has_plate_settings) render_icon_texture(position_id, tex_coords_id, m_plate_settings_icon, m_partplate_list->m_plate_settings_hovered_texture, m_plate_settings_vbo_id); @@ -2936,6 +2936,20 @@ std::vector PartPlate::get_first_layer_print_sequence() const return std::vector(); } +std::vector PartPlate::get_other_layers_print_sequence() const +{ + const ConfigOptionInts* other_layers_print_sequence_op = m_config.option("other_layers_print_sequence"); + const ConfigOptionInt* other_layers_print_sequence_nums_op = m_config.option("other_layers_print_sequence_nums"); + if (other_layers_print_sequence_op && other_layers_print_sequence_nums_op) { + const std::vector& print_sequence = other_layers_print_sequence_op->values; + int sequence_nums = other_layers_print_sequence_nums_op->value; + auto other_layers_seqs = Slic3r::get_other_layers_print_sequence(sequence_nums, print_sequence); + return other_layers_seqs; + } + else + return {}; +} + void PartPlate::set_first_layer_print_sequence(const std::vector& sorted_filaments) { if (sorted_filaments.size() > 0) { @@ -2955,8 +2969,52 @@ void PartPlate::set_first_layer_print_sequence(const std::vector& sorted_fi } } +void PartPlate::set_other_layers_print_sequence(const std::vector& layer_seq_list) +{ + if (layer_seq_list.empty()) { + m_config.erase("other_layers_print_sequence"); + m_config.erase("other_layers_print_sequence_nums"); + return; + } + + int sequence_nums; + std::vector other_layers_seqs; + Slic3r::get_other_layers_print_sequence(layer_seq_list, sequence_nums, other_layers_seqs); + ConfigOptionInts* other_layers_print_sequence_op = m_config.option("other_layers_print_sequence"); + ConfigOptionInt* other_layers_print_sequence_nums_op = m_config.option("other_layers_print_sequence_nums"); + if (other_layers_print_sequence_op) + other_layers_print_sequence_op->values = other_layers_seqs; + else + m_config.set_key_value("other_layers_print_sequence", new ConfigOptionInts(other_layers_seqs)); + if (other_layers_print_sequence_nums_op) + other_layers_print_sequence_nums_op->value = sequence_nums; + else + m_config.set_key_value("other_layers_print_sequence_nums", new ConfigOptionInt(sequence_nums)); +} + void PartPlate::update_first_layer_print_sequence(size_t filament_nums) { + auto other_layers_seqs = get_other_layers_print_sequence(); + if (!other_layers_seqs.empty()) { + bool need_update_data = false; + for (auto& other_layers_seq : other_layers_seqs) { + std::vector& orders = other_layers_seq.second; + if (orders.size() > filament_nums) { + orders.erase(std::remove_if(orders.begin(), orders.end(), [filament_nums](int n) { return n > filament_nums; }), orders.end()); + need_update_data = true; + } + if (orders.size() < filament_nums) { + for (size_t extruder_id = orders.size(); extruder_id < filament_nums; ++extruder_id) { + orders.push_back(extruder_id + 1); + need_update_data = true; + } + } + } + if (need_update_data) + set_other_layers_print_sequence(other_layers_seqs); + } + + ConfigOptionInts * op_print_sequence_1st = m_config.option("first_layer_print_sequence"); if (!op_print_sequence_1st) { return; diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 49b57c0e6..78b3d7782 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -21,6 +21,7 @@ #include "3DScene.hpp" #include "GLModel.hpp" #include "3DBed.hpp" +#include "libslic3r/ParameterUtils.hpp" class GLUquadric; typedef class GLUquadric GLUquadricObject; @@ -477,7 +478,9 @@ public: int load_pattern_box_data(std::string filename); std::vector get_first_layer_print_sequence() const; + std::vector get_other_layers_print_sequence() const; void set_first_layer_print_sequence(const std::vector &sorted_filaments); + void set_other_layers_print_sequence(const std::vector& layer_seq_list); void update_first_layer_print_sequence(size_t filament_nums); void print() const; diff --git a/src/slic3r/GUI/PlateSettingsDialog.cpp b/src/slic3r/GUI/PlateSettingsDialog.cpp index c75267909..d1f39d25c 100644 --- a/src/slic3r/GUI/PlateSettingsDialog.cpp +++ b/src/slic3r/GUI/PlateSettingsDialog.cpp @@ -1,11 +1,362 @@ #include "PlateSettingsDialog.hpp" - +#include "MsgDialog.hpp" namespace Slic3r { namespace GUI { +static constexpr int MIN_LAYER_VALUE = 2; +static constexpr int MAX_LAYER_VALUE = INT_MAX - 1; wxDEFINE_EVENT(EVT_SET_BED_TYPE_CONFIRM, wxCommandEvent); +wxDEFINE_EVENT(EVT_NEED_RESORT_LAYERS, wxCommandEvent); -PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title, bool only_first_layer_seq, const wxPoint& pos, const wxSize& size, long style) +bool LayerSeqInfo::operator<(const LayerSeqInfo& another) const +{ + if (this->begin_layer_number < MIN_LAYER_VALUE) + return false; + if (another.begin_layer_number < MIN_LAYER_VALUE) + return true; + if (this->begin_layer_number == another.begin_layer_number) { + if (this->end_layer_number < MIN_LAYER_VALUE) + return false; + if (another.end_layer_number < MIN_LAYER_VALUE) + return true; + return this->end_layer_number < another.end_layer_number; + } + return this->begin_layer_number < another.begin_layer_number; +} + +LayerNumberTextInput::LayerNumberTextInput(wxWindow* parent, int layer_number, wxSize size, Type type, ValueType value_type) + :ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, size, 0, NULL) + , m_layer_number(layer_number) + , m_type(type) + , m_value_type(value_type) +{ + GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_DIGITS)); + GetTextCtrl()->SetFont(::Label::Body_14); + Append(_L("End")); + Append(_L("Customize")); + if (m_value_type == ValueType::End) + SetSelection(0); + if (m_value_type == ValueType::Custom) { + SetSelection(1); + update_label(); + } + + Bind(wxEVT_TEXT, [this](auto& evt) { + if (m_value_type == ValueType::End) { + // TextCtrl->SetValue() will generate a wxEVT_TEXT event + GetTextCtrl()->ChangeValue(_L("End")); + return; + } + evt.Skip(); + }); + + auto validate_input_value = [this](int gui_value) { + // value should not be less than MIN_LAYER_VALUE, and should not be greater than MAX_LAYER_VALUE + gui_value = std::clamp(gui_value, MIN_LAYER_VALUE, MAX_LAYER_VALUE); + + int begin_value; + int end_value; + LayerNumberTextInput* end_layer_input = nullptr; + if (this->m_type == Type::Begin) { + begin_value = gui_value; + end_value = m_another_layer_input->get_layer_number(); + end_layer_input = m_another_layer_input; + } + if (this->m_type == Type::End) { + begin_value = m_another_layer_input->get_layer_number(); + end_value = gui_value; + end_layer_input = this; + } + + // end value should not be less than begin value + if (begin_value > end_value) { + // set new value for end_layer_input + if (this->m_type == Type::Begin) { + if (end_layer_input->is_layer_number_valid()) { + end_layer_input->set_layer_number(begin_value); + } + } + if (this->m_type == Type::End) { + if (!this->is_layer_number_valid()) { + this->set_layer_number(begin_value); + wxCommandEvent evt(EVT_NEED_RESORT_LAYERS); + wxPostEvent(m_parent, evt); + } + else { + // do nothing + // reset to the last value for end_layer_input + } + return; + } + } + m_layer_number = gui_value; + wxCommandEvent evt(EVT_NEED_RESORT_LAYERS); + wxPostEvent(m_parent, evt); + }; + auto commit_layer_number_from_gui = [this, validate_input_value]() { + if (m_value_type == ValueType::End) + return; + + auto gui_str = GetTextCtrl()->GetValue().ToStdString(); + if (gui_str.empty()) { + m_layer_number = -1; + wxCommandEvent evt(EVT_NEED_RESORT_LAYERS); + wxPostEvent(m_parent, evt); + } + if (!gui_str.empty()) { + int gui_value = atoi(gui_str.c_str()); + validate_input_value(gui_value); + } + update_label(); + }; + Bind(wxEVT_TEXT_ENTER, [commit_layer_number_from_gui](wxEvent& evt) { + commit_layer_number_from_gui(); + evt.Skip(); + }); + Bind(wxEVT_KILL_FOCUS, [commit_layer_number_from_gui](wxFocusEvent& evt) { + commit_layer_number_from_gui(); + evt.Skip(); + }); + + Bind(wxEVT_COMBOBOX, [this](auto& e) { + if (e.GetSelection() == 0) { + m_value_type = ValueType::End; + } + else if (e.GetSelection() == 1) { + m_value_type = ValueType::Custom; + m_layer_number = -1; + update_label(); + } + e.Skip(); + }); +} + +void LayerNumberTextInput::update_label() +{ + if (m_value_type == ValueType::End) + return; + + if (!is_layer_number_valid()) { + SetLabel(""); + } + else + SetLabel(std::to_string(m_layer_number)); +} + +void LayerNumberTextInput::set_layer_number(int layer_number) +{ + m_layer_number = layer_number; + if (layer_number == MAX_LAYER_VALUE) + m_value_type = ValueType::End; + else + m_value_type = ValueType::Custom; + update_label(); +} + +int LayerNumberTextInput::get_layer_number() +{ + return m_value_type == ValueType::End ? MAX_LAYER_VALUE : m_layer_number; +} + +bool LayerNumberTextInput::is_layer_number_valid() +{ + if (m_value_type == ValueType::End) + return true; + return m_layer_number >= MIN_LAYER_VALUE; +} + +OtherLayersSeqPanel::OtherLayersSeqPanel(wxWindow* parent) + :wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) +{ + m_bmp_delete = ScalableBitmap(this, "delete_filament"); + m_bmp_add = ScalableBitmap(this, "add_filament"); + + SetBackgroundColour(*wxWHITE); + + wxBoxSizer* top_sizer = new wxBoxSizer(wxVERTICAL); + + wxBoxSizer* title_sizer = new wxBoxSizer(wxHORIZONTAL); + m_other_layer_print_seq_choice = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240), -1), 0, NULL, wxCB_READONLY); + m_other_layer_print_seq_choice->Append(_L("Auto")); + m_other_layer_print_seq_choice->Append(_L("Customize")); + m_other_layer_print_seq_choice->SetSelection(0); + wxStaticText* other_layer_txt = new wxStaticText(this, wxID_ANY, _L("Other layer filament sequence")); + other_layer_txt->SetFont(Label::Body_14); + title_sizer->Add(other_layer_txt, 0, wxALIGN_CENTER | wxALIGN_LEFT, 0); + title_sizer->AddStretchSpacer(); + title_sizer->Add(m_other_layer_print_seq_choice, 0, wxALIGN_CENTER | wxALIGN_RIGHT, 0); + + wxBoxSizer* buttons_sizer = new wxBoxSizer(wxHORIZONTAL); + ScalableButton* add_layers_btn = new ScalableButton(this, wxID_ANY, m_bmp_add); + add_layers_btn->SetBackgroundColour(GetBackgroundColour()); + ScalableButton* delete_layers_btn = new ScalableButton(this, wxID_ANY, m_bmp_delete); + delete_layers_btn->SetBackgroundColour(GetBackgroundColour()); + buttons_sizer->Add(add_layers_btn, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, FromDIP(5)); + buttons_sizer->Add(delete_layers_btn, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, FromDIP(5)); + buttons_sizer->Show(false); + + m_layer_input_panel = new wxPanel(this); + wxBoxSizer* layer_panel_sizer = new wxBoxSizer(wxVERTICAL); + m_layer_input_panel->SetSizer(layer_panel_sizer); + m_layer_input_panel->Hide(); + append_layer(); + + top_sizer->Add(title_sizer, 0, wxEXPAND, 0); + top_sizer->Add(buttons_sizer, 0, wxALIGN_CENTER, 0); + top_sizer->Add(m_layer_input_panel, 0, wxEXPAND, 0); + + SetSizer(top_sizer); + Layout(); + top_sizer->Fit(this); + + + m_other_layer_print_seq_choice->Bind(wxEVT_COMBOBOX, [this, buttons_sizer](auto& e) { + if (e.GetSelection() == 0) { + m_layer_input_panel->Show(false); + buttons_sizer->Show(false); + } + else if (e.GetSelection() == 1) { + m_layer_input_panel->Show(true); + buttons_sizer->Show(true); + } + m_parent->Layout(); + m_parent->Fit(); + }); + add_layers_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { + Freeze(); + append_layer(); + m_parent->Layout(); + m_parent->Fit(); + Thaw(); + }); + delete_layers_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { + popup_layer(); + m_parent->Layout(); + m_parent->Fit(); + }); + Bind(EVT_NEED_RESORT_LAYERS, [this](auto& evt) { + std::vector result; + for (int i = 0; i < m_layer_input_sizer_list.size(); i++) { + int begin_layer_number = m_begin_layer_input_list[i]->get_layer_number(); + int end_layer_number = m_end_layer_input_list[i]->get_layer_number(); + result.push_back({ begin_layer_number, end_layer_number, m_drag_canvas_list[i]->get_shape_list_order() }); + } + if (!std::is_sorted(result.begin(), result.end())) { + std::sort(result.begin(), result.end()); + sync_layers_print_seq(1, result); + } + result.swap(m_layer_seq_infos); + }); + Bind(EVT_SET_BED_TYPE_CONFIRM, [this](auto& evt) { + std::vector result; + for (int i = 0; i < m_layer_input_sizer_list.size(); i++) { + int begin_layer_number = m_begin_layer_input_list[i]->get_layer_number(); + int end_layer_number = m_end_layer_input_list[i]->get_layer_number(); + + if (!m_begin_layer_input_list[i]->is_layer_number_valid() || !m_end_layer_input_list[i]->is_layer_number_valid()) { + MessageDialog msg_dlg(nullptr, _L("Please input layer value (>= 2)."), wxEmptyString, wxICON_WARNING | wxOK); + msg_dlg.ShowModal(); + evt.SetString("Invalid"); + return; + } + + result.push_back({ begin_layer_number, end_layer_number, m_drag_canvas_list[i]->get_shape_list_order() }); + } + result.swap(m_layer_seq_infos); + }); +} + +void OtherLayersSeqPanel::append_layer(const LayerSeqInfo* layer_info) +{ + wxBoxSizer* layer_panel_sizer = static_cast(m_layer_input_panel->GetSizer()); + + wxStaticText* choose_layer_head_txt = new wxStaticText(m_layer_input_panel, wxID_ANY, _L("Layer")); + choose_layer_head_txt->SetFont(Label::Body_14); + + LayerNumberTextInput* begin_layer_input = new LayerNumberTextInput(m_layer_input_panel, -1, wxSize(FromDIP(100), -1), LayerNumberTextInput::Type::Begin, LayerNumberTextInput::ValueType::Custom); + + wxStaticText* choose_layer_to_txt = new wxStaticText(m_layer_input_panel, wxID_ANY, _L("to")); + choose_layer_to_txt->SetFont(Label::Body_14); + + LayerNumberTextInput* end_layer_input = new LayerNumberTextInput(m_layer_input_panel, -1, wxSize(FromDIP(100), -1), LayerNumberTextInput::Type::End, LayerNumberTextInput::ValueType::End); + + begin_layer_input->link(end_layer_input); + if (m_begin_layer_input_list.size() == 0) { + begin_layer_input->set_layer_number(MIN_LAYER_VALUE); + end_layer_input->set_layer_number(MAX_LAYER_VALUE); + } + + const std::vector extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config(); + std::vector order(extruder_colours.size()); + for (int i = 0; i < order.size(); i++) { + order[i] = i + 1; + } + auto drag_canvas = new DragCanvas(m_layer_input_panel, extruder_colours, order); + + if (layer_info) { + begin_layer_input->set_layer_number(layer_info->begin_layer_number); + end_layer_input->set_layer_number(layer_info->end_layer_number); + drag_canvas->set_shape_list(extruder_colours, layer_info->print_sequence); + } + + wxBoxSizer* single_layer_input_sizer = new wxBoxSizer(wxHORIZONTAL); + single_layer_input_sizer->Add(choose_layer_head_txt, 0, wxRIGHT | wxALIGN_CENTER, FromDIP(5)); + single_layer_input_sizer->Add(begin_layer_input, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, FromDIP(5)); + single_layer_input_sizer->Add(choose_layer_to_txt, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, 0); + single_layer_input_sizer->Add(end_layer_input, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER, FromDIP(5)); + single_layer_input_sizer->AddStretchSpacer(); + single_layer_input_sizer->Add(drag_canvas, 0, wxLEFT | wxALIGN_CENTER, FromDIP(5)); + layer_panel_sizer->Add(single_layer_input_sizer, 0, wxEXPAND | wxALIGN_CENTER | wxBOTTOM, FromDIP(10)); + m_layer_input_sizer_list.push_back(single_layer_input_sizer); + m_begin_layer_input_list.push_back(begin_layer_input); + m_end_layer_input_list.push_back(end_layer_input); + m_drag_canvas_list.push_back(drag_canvas); +} + +void OtherLayersSeqPanel::popup_layer() +{ + if (m_layer_input_sizer_list.size() > 1) { + m_layer_input_sizer_list.back()->Clear(true); + m_layer_input_sizer_list.pop_back(); + m_begin_layer_input_list.pop_back(); + m_end_layer_input_list.pop_back(); + m_drag_canvas_list.pop_back(); + } +} + +void OtherLayersSeqPanel::clear_all_layers() +{ + for (auto sizer : m_layer_input_sizer_list) { + sizer->Clear(true); + } + m_layer_input_sizer_list.clear(); + m_begin_layer_input_list.clear(); + m_end_layer_input_list.clear(); + m_drag_canvas_list.clear(); +} + +void OtherLayersSeqPanel::sync_layers_print_seq(int selection, const std::vector& seq) +{ + if (m_other_layer_print_seq_choice != nullptr) { + if (selection == 1) { + clear_all_layers(); + Freeze(); + for (int i = 0; i < seq.size(); i++) { + append_layer(&seq[i]); + } + Thaw(); + } + m_other_layer_print_seq_choice->SetSelection(selection); + + wxCommandEvent event(wxEVT_COMBOBOX); + event.SetInt(selection); + event.SetEventObject(m_other_layer_print_seq_choice); + wxPostEvent(m_other_layer_print_seq_choice, event); + } +} + + +PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title, bool only_layer_seq, const wxPoint& pos, const wxSize& size, long style) :DPIDialog(parent, wxID_ANY, title, pos, size, style) { std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); @@ -13,10 +364,9 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title SetBackgroundColour(*wxWHITE); wxBoxSizer* m_sizer_main = new wxBoxSizer(wxVERTICAL); - auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(400), -1)); + auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(650), -1)); m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0); - m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5)); wxFlexGridSizer* top_sizer = new wxFlexGridSizer(0, 2, FromDIP(5), 0); top_sizer->AddGrowableCol(0,1); @@ -29,10 +379,9 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title } wxStaticText* m_bed_type_txt = new wxStaticText(this, wxID_ANY, _L("Bed type")); m_bed_type_txt->SetFont(Label::Body_14); - top_sizer->Add(m_bed_type_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); - top_sizer->Add(m_bed_type_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT |wxALL, FromDIP(5)); + top_sizer->Add(m_bed_type_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxTOP | wxBOTTOM, FromDIP(5)); + top_sizer->Add(m_bed_type_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxTOP | wxBOTTOM, FromDIP(5)); - wxBoxSizer* m_sizer_selectbox = new wxBoxSizer(wxHORIZONTAL); m_print_seq_choice = new ComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240),-1), 0, NULL, wxCB_READONLY ); m_print_seq_choice->Append(_L("Same as Global Print Sequence")); for (auto i = PrintSequence::ByLayer; i < PrintSequence::ByDefault; i = PrintSequence(int(i) + 1)) { @@ -40,9 +389,10 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title } wxStaticText* m_print_seq_txt = new wxStaticText(this, wxID_ANY, _L("Print sequence")); m_print_seq_txt->SetFont(Label::Body_14); - top_sizer->Add(m_print_seq_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT |wxALL, FromDIP(5)); - top_sizer->Add(m_print_seq_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT |wxALL, FromDIP(5)); + top_sizer->Add(m_print_seq_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxTOP | wxBOTTOM, FromDIP(5)); + top_sizer->Add(m_print_seq_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxTOP | wxBOTTOM, FromDIP(5)); + // first layer filament sequence m_first_layer_print_seq_choice = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240), -1), 0, NULL, wxCB_READONLY); m_first_layer_print_seq_choice->Append(_L("Auto")); m_first_layer_print_seq_choice->Append(_L("Customize")); @@ -59,22 +409,28 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title }); wxStaticText* first_layer_txt = new wxStaticText(this, wxID_ANY, _L("First layer filament sequence")); first_layer_txt->SetFont(Label::Body_14); - top_sizer->Add(first_layer_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); - top_sizer->Add(m_first_layer_print_seq_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, FromDIP(5)); + top_sizer->Add(first_layer_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxTOP | wxBOTTOM, FromDIP(5)); + top_sizer->Add(m_first_layer_print_seq_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxTOP | wxBOTTOM, FromDIP(5)); const std::vector extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config(); - std::vector order; - if (order.empty()) { - for (int i = 1; i <= extruder_colours.size(); i++) { - order.push_back(i); - } + std::vector order(extruder_colours.size()); + for (int i = 0; i < order.size(); i++) { + order[i] = i + 1; } m_drag_canvas = new DragCanvas(this, extruder_colours, order); m_drag_canvas->Hide(); - top_sizer->Add(0, 0, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(0)); - top_sizer->Add(m_drag_canvas, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5)); + top_sizer->Add(0, 0, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT, 0); + top_sizer->Add(m_drag_canvas, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxBOTTOM, FromDIP(10)); + + m_sizer_main->Add(top_sizer, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, FromDIP(30)); + + // Other layer filament sequence + m_other_layers_seq_panel = new OtherLayersSeqPanel(this); + m_sizer_main->AddSpacer(FromDIP(5)); + m_sizer_main->Add(m_other_layers_seq_panel, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(30)); // hidden + // spiral mode //m_spiral_mode_choice = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240), -1), 0, NULL, wxCB_READONLY); //m_spiral_mode_choice->Append(_L("Same as Global")); //m_spiral_mode_choice->Append(_L("Enable")); @@ -86,8 +442,6 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title //top_sizer->Add(m_spiral_mode_choice, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, FromDIP(5)); - m_sizer_main->Add(top_sizer, 0, wxEXPAND | wxALL, FromDIP(30)); - auto sizer_button = new wxBoxSizer(wxHORIZONTAL); StateColor btn_bg_green(std::pair(wxColour(27, 136, 68), StateColor::Pressed), std::pair(wxColour(61, 203, 115), StateColor::Hovered), std::pair(wxColour(0, 174, 66), StateColor::Normal)); @@ -103,10 +457,12 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title m_button_ok->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); m_button_ok->SetCornerRadius(FromDIP(12)); - m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { + m_button_ok->Bind(wxEVT_BUTTON, [this](auto& e) { wxCommandEvent evt(EVT_SET_BED_TYPE_CONFIRM, GetId()); - e.SetEventObject(this); + static_cast(m_other_layers_seq_panel)->ProcessEvent(evt); GetEventHandler()->ProcessEvent(evt); + if (evt.GetString() == "Invalid") + return; if (this->IsModal()) EndModal(wxID_YES); else @@ -120,7 +476,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title m_button_cancel->SetSize(wxSize(FromDIP(58), FromDIP(24))); m_button_cancel->SetMinSize(wxSize(FromDIP(58), FromDIP(24))); m_button_cancel->SetCornerRadius(FromDIP(12)); - m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { + m_button_cancel->Bind(wxEVT_BUTTON, [this](auto& e) { if (this->IsModal()) EndModal(wxID_NO); else @@ -132,7 +488,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title sizer_button->Add(m_button_cancel, 0, wxALL, FromDIP(5)); sizer_button->Add(FromDIP(30),0, 0, 0); - m_sizer_main->Add(sizer_button, 0, wxEXPAND, FromDIP(20)); + m_sizer_main->Add(sizer_button, 0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(20)); SetSizer(m_sizer_main); Layout(); @@ -142,7 +498,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title wxGetApp().UpdateDlgDarkUI(this); - if (only_first_layer_seq) { + if (only_layer_seq) { for (auto item : top_sizer->GetChildren()) { if (item->GetWindow()) item->GetWindow()->Show(false); @@ -150,6 +506,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title first_layer_txt->Show(); m_first_layer_print_seq_choice->Show(); m_drag_canvas->Show(); + m_other_layers_seq_panel->Show(); Layout(); Fit(); } @@ -190,6 +547,21 @@ void PlateSettingsDialog::sync_first_layer_print_seq(int selection, const std::v } } +void PlateSettingsDialog::sync_other_layers_print_seq(int selection, const std::vector& seq) { + if (selection == 1) { + std::vector sequences; + sequences.reserve(seq.size()); + for (int i = 0; i < seq.size(); i++) { + LayerSeqInfo info{ seq[i].first.first, seq[i].first.second, seq[i].second }; + sequences.push_back(info); + } + m_other_layers_seq_panel->sync_layers_print_seq(selection, sequences); + } + else { + m_other_layers_seq_panel->sync_layers_print_seq(selection, {}); + } +} + void PlateSettingsDialog::sync_spiral_mode(bool spiral_mode, bool as_global) { if (m_spiral_mode_choice) { @@ -344,4 +716,6 @@ void PlateNameEditDialog::set_plate_name(const wxString &name) { m_ti_plate_name->GetTextCtrl()->SetInsertionPointEnd(); } -}} // namespace Slic3r::GUI \ No newline at end of file + +} +} // namespace Slic3r::GUI \ No newline at end of file diff --git a/src/slic3r/GUI/PlateSettingsDialog.hpp b/src/slic3r/GUI/PlateSettingsDialog.hpp index 2ee3c5550..3f43afdd1 100644 --- a/src/slic3r/GUI/PlateSettingsDialog.hpp +++ b/src/slic3r/GUI/PlateSettingsDialog.hpp @@ -7,10 +7,78 @@ #include "Widgets/RadioBox.hpp" #include "Widgets/ComboBox.hpp" #include "DragCanvas.hpp" +#include "libslic3r/ParameterUtils.hpp" namespace Slic3r { namespace GUI { wxDECLARE_EVENT(EVT_SET_BED_TYPE_CONFIRM, wxCommandEvent); +wxDECLARE_EVENT(EVT_NEED_RESORT_LAYERS, wxCommandEvent); + +struct LayerSeqInfo { + int begin_layer_number; + int end_layer_number; + std::vector print_sequence; + + bool operator<(const LayerSeqInfo& another) const; +}; + +class LayerNumberTextInput : public ComboBox { +public: + enum class Type { + Begin, + End + }; + enum class ValueType { + Custom, + End + }; + LayerNumberTextInput(wxWindow* parent, int layer_number, wxSize size, Type type, ValueType value_type = ValueType::Custom); + void link(LayerNumberTextInput* layer_input) { + if (m_another_layer_input) return; + m_another_layer_input = layer_input; + layer_input->link(this); } + void set_layer_number(int layer_number); + int get_layer_number(); + Type get_input_type() { return m_type; } + ValueType get_value_type() { return m_value_type; } + bool is_layer_number_valid(); + +protected: + void update_label(); + +private: + LayerNumberTextInput* m_another_layer_input{ nullptr }; + int m_layer_number; + Type m_type; + ValueType m_value_type; +}; + +class OtherLayersSeqPanel : public wxPanel { +public: + OtherLayersSeqPanel(wxWindow* parent); + + void sync_layers_print_seq(int selection, const std::vector& seq); + + int get_layers_print_seq_choice() { return m_other_layer_print_seq_choice->GetSelection(); }; + + std::vector get_layers_print_seq_infos() { return m_layer_seq_infos; } + +protected: + void append_layer(const LayerSeqInfo* layer_info = nullptr); + void popup_layer(); + void clear_all_layers(); + +private: + ScalableBitmap m_bmp_delete; + ScalableBitmap m_bmp_add; + ComboBox* m_other_layer_print_seq_choice{ nullptr }; + wxPanel* m_layer_input_panel{ nullptr }; + std::vector m_layer_input_sizer_list; + std::vector m_begin_layer_input_list; + std::vector m_end_layer_input_list; + std::vector m_drag_canvas_list; + std::vector m_layer_seq_infos; +}; class PlateSettingsDialog : public DPIDialog { @@ -23,7 +91,7 @@ public: PlateSettingsDialog( wxWindow* parent, const wxString& title = wxEmptyString, - bool only_first_layer_seq = false, + bool only_layer_seq = false, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCLOSE_BOX | wxCAPTION @@ -33,6 +101,7 @@ public: void sync_bed_type(BedType type); void sync_print_seq(int print_seq = 0); void sync_first_layer_print_seq(int selection, const std::vector& seq = std::vector()); + void sync_other_layers_print_seq(int selection, const std::vector& seq); void sync_spiral_mode(bool spiral_mode, bool as_global); wxString to_bed_type_name(BedType bed_type); wxString to_print_sequence_name(PrintSequence print_seq); @@ -59,8 +128,25 @@ public: return choice; }; + int get_other_layers_print_seq_choice() { + if (m_other_layers_seq_panel) + return m_other_layers_seq_panel->get_layers_print_seq_choice(); + return 0; + }; + std::vector get_first_layer_print_seq(); + std::vector get_other_layers_print_seq_infos() { + const std::vector& layer_seq_infos = m_other_layers_seq_panel->get_layers_print_seq_infos(); + std::vector result; + result.reserve(layer_seq_infos.size()); + for (int i = 0; i < layer_seq_infos.size(); i++) { + LayerPrintSequence item = std::make_pair(std::make_pair(layer_seq_infos[i].begin_layer_number, layer_seq_infos[i].end_layer_number), layer_seq_infos[i].print_sequence); + result.push_back(item); + } + return result; + } + int get_spiral_mode_choice() { int choice = 0; if (m_spiral_mode_choice != nullptr) @@ -72,12 +158,17 @@ public: return false; } +protected: + void add_layers(); + void delete_layers(); + protected: ComboBox* m_bed_type_choice { nullptr }; ComboBox* m_print_seq_choice { nullptr }; ComboBox* m_first_layer_print_seq_choice { nullptr }; ComboBox* m_spiral_mode_choice { nullptr }; DragCanvas* m_drag_canvas; + OtherLayersSeqPanel* m_other_layers_seq_panel; Button* m_button_ok; Button* m_button_cancel; }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 67e141873..0bbcb61bf 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -13006,7 +13006,7 @@ void Plater::validate_current_plate(bool& model_fits, bool& validate_error) void Plater::open_platesettings_dialog(wxCommandEvent& evt) { int plate_index = evt.GetInt(); - PlateSettingsDialog dlg(this, _L("Plate Settings"), evt.GetString() == "only_first_layer_sequence"); + PlateSettingsDialog dlg(this, _L("Plate Settings"), evt.GetString() == "only_layer_sequence"); PartPlate* curr_plate = p->partplate_list.get_curr_plate(); dlg.sync_bed_type(curr_plate->get_bed_type()); @@ -13023,6 +13023,13 @@ void Plater::open_platesettings_dialog(wxCommandEvent& evt) { else dlg.sync_first_layer_print_seq(1, curr_plate->get_first_layer_print_sequence()); + auto other_layers_print_seq = curr_plate->get_other_layers_print_sequence(); + if (other_layers_print_seq.empty()) + dlg.sync_other_layers_print_seq(0, {}); + else { + dlg.sync_other_layers_print_seq(1, curr_plate->get_other_layers_print_sequence()); + } + dlg.sync_spiral_mode(curr_plate->get_spiral_vase_mode(), !curr_plate->has_spiral_mode_config()); dlg.Bind(EVT_SET_BED_TYPE_CONFIRM, [this, plate_index, &dlg](wxCommandEvent& e) { @@ -13041,6 +13048,11 @@ void Plater::open_platesettings_dialog(wxCommandEvent& evt) { else curr_plate->set_first_layer_print_sequence({}); + if (dlg.get_other_layers_print_seq_choice() != 0) + curr_plate->set_other_layers_print_sequence(dlg.get_other_layers_print_seq_infos()); + else + curr_plate->set_other_layers_print_sequence({}); + int ps_sel = dlg.get_print_seq_choice(); if (ps_sel != 0) curr_plate->set_print_seq(PrintSequence(ps_sel - 1)); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 8b8481537..cfc875655 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2375,12 +2375,18 @@ void TabPrintModel::update_model_config() } } if (!plate_config.has("first_layer_print_sequence")) { - // same as global - m_config->set_key_value("first_layer_sequence_choice", new ConfigOptionEnum(flsAuto)); + m_config->set_key_value("first_layer_sequence_choice", new ConfigOptionEnum(flsAuto)); } else { replace(m_all_keys.begin(), m_all_keys.end(), std::string("first_layer_print_sequence"), std::string("first_layer_sequence_choice")); - m_config->set_key_value("first_layer_sequence_choice", new ConfigOptionEnum(flsCutomize)); + m_config->set_key_value("first_layer_sequence_choice", new ConfigOptionEnum(flsCutomize)); + } + if (!plate_config.has("other_layers_print_sequence")) { + m_config->set_key_value("other_layers_sequence_choice", new ConfigOptionEnum(flsAuto)); + } + else { + replace(m_all_keys.begin(), m_all_keys.end(), std::string("other_layers_print_sequence"), std::string("other_layers_sequence_choice")); + m_config->set_key_value("other_layers_sequence_choice", new ConfigOptionEnum(flsCutomize)); } notify_changed(plate_item.first); } @@ -2506,7 +2512,7 @@ void TabPrintModel::update_custom_dirty() } //BBS: GUI refactor -static const std::vector plate_keys = { "curr_bed_type", "first_layer_print_sequence", "first_layer_sequence_choice", "print_sequence"/*, "spiral_mode"*/}; +static const std::vector plate_keys = { "curr_bed_type", "first_layer_print_sequence", "first_layer_sequence_choice", "other_layers_print_sequence", "other_layers_sequence_choice", "print_sequence"/*, "spiral_mode"*/}; TabPrintPlate::TabPrintPlate(ParamsPanel* parent) : TabPrintModel(parent, plate_keys) { @@ -2528,12 +2534,15 @@ void TabPrintPlate::build() } m_config->option("first_layer_sequence_choice", true); m_config->option("first_layer_print_sequence", true); + m_config->option("other_layers_print_sequence", true); + m_config->option("other_layers_sequence_choice", true); auto page = add_options_page(L("Plate Settings"), "empty"); auto optgroup = page->new_optgroup(""); optgroup->append_single_option_line("curr_bed_type"); optgroup->append_single_option_line("print_sequence"); optgroup->append_single_option_line("first_layer_sequence_choice"); + optgroup->append_single_option_line("other_layers_sequence_choice"); // hidden //optgroup->append_single_option_line("spiral_mode"); for (auto& line : const_cast&>(optgroup->get_lines())) { @@ -2583,6 +2592,8 @@ void TabPrintPlate::on_value_change(const std::string& opt_key, const boost::any plate->set_print_seq(PrintSequence::ByDefault); if (k == "first_layer_sequence_choice") plate->set_first_layer_print_sequence({}); + if (k == "other_layers_sequence_choice") + plate->set_other_layers_print_sequence({}); if (k == "spiral_mode") plate->set_spiral_vase_mode(false, true); } @@ -2594,7 +2605,8 @@ void TabPrintPlate::on_value_change(const std::string& opt_key, const boost::any auto plate = dynamic_cast(plate_item.first); BedType bed_type; PrintSequence print_seq; - FirstLayerSeq first_layer_seq_choice; + LayerSeq first_layer_seq_choice; + LayerSeq other_layer_seq_choice; if (k == "curr_bed_type") { bed_type = m_config->opt_enum("curr_bed_type"); plate->set_bed_type(BedType(bed_type)); @@ -2604,11 +2616,11 @@ void TabPrintPlate::on_value_change(const std::string& opt_key, const boost::any plate->set_print_seq(print_seq); } if (k == "first_layer_sequence_choice") { - first_layer_seq_choice = m_config->opt_enum("first_layer_sequence_choice"); - if (first_layer_seq_choice == FirstLayerSeq::flsAuto) { + first_layer_seq_choice = m_config->opt_enum("first_layer_sequence_choice"); + if (first_layer_seq_choice == LayerSeq::flsAuto) { plate->set_first_layer_print_sequence({}); } - else if (first_layer_seq_choice == FirstLayerSeq::flsCutomize) { + else if (first_layer_seq_choice == LayerSeq::flsCutomize) { const DynamicPrintConfig& plate_config = plate_item.second->get(); if (!plate_config.has("first_layer_print_sequence")) { std::vector initial_sequence; @@ -2619,9 +2631,30 @@ void TabPrintPlate::on_value_change(const std::string& opt_key, const boost::any } wxCommandEvent evt(EVT_OPEN_PLATESETTINGSDIALOG); evt.SetInt(plate->get_index()); - evt.SetString("only_first_layer_sequence"); + evt.SetString("only_layer_sequence"); + evt.SetEventObject(wxGetApp().plater()); + wxPostEvent(wxGetApp().plater(), evt); + } + } + if (k == "other_layers_sequence_choice") { + other_layer_seq_choice = m_config->opt_enum("other_layers_sequence_choice"); + if (other_layer_seq_choice == LayerSeq::flsAuto) { + plate->set_other_layers_print_sequence({}); + } + else if (other_layer_seq_choice == LayerSeq::flsCutomize) { + const DynamicPrintConfig& plate_config = plate_item.second->get(); + if (!plate_config.has("other_layers_print_sequence")) { + std::vector initial_sequence; + for (int i = 0; i < wxGetApp().filaments_cnt(); i++) { + initial_sequence.push_back(i + 1); + } + std::vector initial_layer_sequence{ std::make_pair(std::make_pair(2, INT_MAX), initial_sequence) }; + plate->set_other_layers_print_sequence(initial_layer_sequence); + } + wxCommandEvent evt(EVT_OPEN_PLATESETTINGSDIALOG); + evt.SetInt(plate->get_index()); + evt.SetString("only_layer_sequence"); evt.SetEventObject(wxGetApp().plater()); - //wxGetApp().plater()->GetEventHandler()->ProcessEvent(evt); wxPostEvent(wxGetApp().plater(), evt); } } @@ -2662,8 +2695,11 @@ void TabPrintPlate::update_custom_dirty() for (auto k : m_null_keys) m_options_list[k] = 0; for (auto k : m_all_keys) { - if (k == "first_layer_sequence_choice") { - if (m_config->opt_enum("first_layer_sequence_choice") != FirstLayerSeq::flsAuto) { + if (k == "first_layer_sequence_choice" || k == "other_layers_sequence_choice") { + if (m_config->opt_enum("first_layer_sequence_choice") != LayerSeq::flsAuto) { + m_options_list[k] &= ~osInitValue; + } + if (m_config->opt_enum("other_layers_sequence_choice") != LayerSeq::flsAuto) { m_options_list[k] &= ~osInitValue; } }