NEW: support to adjust other layers print sequence

Jira: 6338

Change-Id: I5e6aef71aa9e6e97c1859aaaeb9ada5f1340414a
This commit is contained in:
liz.li 2024-02-26 15:38:23 +08:00 committed by Lane.Wei
parent 93078d0911
commit dab9a98e0d
10 changed files with 639 additions and 47 deletions

View File

@ -15,7 +15,7 @@ std::vector<LayerPrintSequence> get_other_layers_print_sequence(int sequence_num
for (int i = 0; i < sequence_nums; ++i) {
std::vector<int> 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::pair<int, int>, std::vector<int>> res_item;
@ -36,6 +36,8 @@ void get_other_layers_print_sequence(const std::vector<LayerPrintSequence> &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());
}
}

View File

@ -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<FirstLayerSeq>::get_enum_values();
def->enum_keys_map = &ConfigOptionEnum<LayerSeq>::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<FirstLayerSeq>(flsAuto));
def->set_default_value(new ConfigOptionEnum<LayerSeq>(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<LayerSeq>::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<LayerSeq>(flsAuto));
def = this->add("before_layer_change_gcode", coString);
def->label = L("Before layer change G-code");

View File

@ -210,7 +210,7 @@ enum BedType {
};
// BBS
enum FirstLayerSeq {
enum LayerSeq {
flsAuto,
flsCutomize
};

View File

@ -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;

View File

@ -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<int> PartPlate::get_first_layer_print_sequence() const
return std::vector<int>();
}
std::vector<LayerPrintSequence> PartPlate::get_other_layers_print_sequence() const
{
const ConfigOptionInts* other_layers_print_sequence_op = m_config.option<ConfigOptionInts>("other_layers_print_sequence");
const ConfigOptionInt* other_layers_print_sequence_nums_op = m_config.option<ConfigOptionInt>("other_layers_print_sequence_nums");
if (other_layers_print_sequence_op && other_layers_print_sequence_nums_op) {
const std::vector<int>& 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<int>& sorted_filaments)
{
if (sorted_filaments.size() > 0) {
@ -2955,8 +2969,52 @@ void PartPlate::set_first_layer_print_sequence(const std::vector<int>& sorted_fi
}
}
void PartPlate::set_other_layers_print_sequence(const std::vector<LayerPrintSequence>& 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<int> 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<ConfigOptionInts>("other_layers_print_sequence");
ConfigOptionInt* other_layers_print_sequence_nums_op = m_config.option<ConfigOptionInt>("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<int>& 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<ConfigOptionInts>("first_layer_print_sequence");
if (!op_print_sequence_1st) {
return;

View File

@ -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<int> get_first_layer_print_sequence() const;
std::vector<LayerPrintSequence> get_other_layers_print_sequence() const;
void set_first_layer_print_sequence(const std::vector<int> &sorted_filaments);
void set_other_layers_print_sequence(const std::vector<LayerPrintSequence>& layer_seq_list);
void update_first_layer_print_sequence(size_t filament_nums);
void print() const;

View File

@ -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<LayerSeqInfo> 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<LayerSeqInfo> 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<wxBoxSizer*>(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<std::string> extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config();
std::vector<int> 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<LayerSeqInfo>& 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<std::string> extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config();
std::vector<int> order;
if (order.empty()) {
for (int i = 1; i <= extruder_colours.size(); i++) {
order.push_back(i);
}
std::vector<int> 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, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(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<wxEvtHandler*>(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<LayerPrintSequence>& seq) {
if (selection == 1) {
std::vector<LayerSeqInfo> 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
}
} // namespace Slic3r::GUI

View File

@ -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<int> 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<LayerSeqInfo>& seq);
int get_layers_print_seq_choice() { return m_other_layer_print_seq_choice->GetSelection(); };
std::vector<LayerSeqInfo> 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<wxBoxSizer*> m_layer_input_sizer_list;
std::vector<LayerNumberTextInput*> m_begin_layer_input_list;
std::vector<LayerNumberTextInput*> m_end_layer_input_list;
std::vector<DragCanvas*> m_drag_canvas_list;
std::vector<LayerSeqInfo> 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<int>& seq = std::vector<int>());
void sync_other_layers_print_seq(int selection, const std::vector<LayerPrintSequence>& 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<int> get_first_layer_print_seq();
std::vector<LayerPrintSequence> get_other_layers_print_seq_infos() {
const std::vector<LayerSeqInfo>& layer_seq_infos = m_other_layers_seq_panel->get_layers_print_seq_infos();
std::vector<LayerPrintSequence> 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;
};

View File

@ -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));

View File

@ -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<FirstLayerSeq>(flsAuto));
m_config->set_key_value("first_layer_sequence_choice", new ConfigOptionEnum<LayerSeq>(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<FirstLayerSeq>(flsCutomize));
m_config->set_key_value("first_layer_sequence_choice", new ConfigOptionEnum<LayerSeq>(flsCutomize));
}
if (!plate_config.has("other_layers_print_sequence")) {
m_config->set_key_value("other_layers_sequence_choice", new ConfigOptionEnum<LayerSeq>(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<LayerSeq>(flsCutomize));
}
notify_changed(plate_item.first);
}
@ -2506,7 +2512,7 @@ void TabPrintModel::update_custom_dirty()
}
//BBS: GUI refactor
static const std::vector<std::string> plate_keys = { "curr_bed_type", "first_layer_print_sequence", "first_layer_sequence_choice", "print_sequence"/*, "spiral_mode"*/};
static const std::vector<std::string> 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<std::vector<Line>&>(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<PartPlate*>(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<BedType>("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<FirstLayerSeq>("first_layer_sequence_choice");
if (first_layer_seq_choice == FirstLayerSeq::flsAuto) {
first_layer_seq_choice = m_config->opt_enum<LayerSeq>("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<int> 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<LayerSeq>("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<int> initial_sequence;
for (int i = 0; i < wxGetApp().filaments_cnt(); i++) {
initial_sequence.push_back(i + 1);
}
std::vector<LayerPrintSequence> 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<FirstLayerSeq>("first_layer_sequence_choice") != FirstLayerSeq::flsAuto) {
if (k == "first_layer_sequence_choice" || k == "other_layers_sequence_choice") {
if (m_config->opt_enum<LayerSeq>("first_layer_sequence_choice") != LayerSeq::flsAuto) {
m_options_list[k] &= ~osInitValue;
}
if (m_config->opt_enum<LayerSeq>("other_layers_sequence_choice") != LayerSeq::flsAuto) {
m_options_list[k] &= ~osInitValue;
}
}