diff --git a/resources/images/ams_1_tray.svg b/resources/images/ams_1_tray.svg
new file mode 100644
index 000000000..ed37c408b
--- /dev/null
+++ b/resources/images/ams_1_tray.svg
@@ -0,0 +1,5 @@
+
diff --git a/resources/images/ams_4_tray.svg b/resources/images/ams_4_tray.svg
new file mode 100644
index 000000000..7ebcac7bf
--- /dev/null
+++ b/resources/images/ams_4_tray.svg
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index ee439b3fd..62cd73799 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -327,8 +327,14 @@ struct Sidebar::priv
wxPanel* m_panel_print_title;
wxStaticText* m_staticText_print_title;
wxPanel* m_panel_print_content;
- wxComboBox* m_comboBox_print_preset;
- wxStaticLine* m_staticline1;
+ //wxComboBox * m_comboBox_print_preset;
+ ComboBox * m_bed_type_list = nullptr;
+ ComboBox * m_left_extruder_list = nullptr;
+ wxStaticText * m_left_ams_count = nullptr;
+ ComboBox * m_right_extruder_list = nullptr;
+ wxStaticText * m_right_ams_count = nullptr;
+ wxSizer * m_dual_extruder_sizer = nullptr;
+ wxStaticLine * m_staticline1;
StaticBox* m_panel_filament_title;
wxStaticText* m_staticText_filament_settings;
ScalableButton * m_bpButton_add_filament;
@@ -348,7 +354,8 @@ struct Sidebar::priv
StaticBox* m_panel_printer_title = nullptr;
ScalableButton* m_printer_icon = nullptr;
ScalableButton* m_printer_setting = nullptr;
- wxStaticText* m_text_printer_settings = nullptr;
+ ScalableButton *m_extruder_sync = nullptr;
+ wxStaticText * m_text_printer_settings = nullptr;
wxPanel* m_panel_printer_content = nullptr;
ObjectList *m_object_list{ nullptr };
@@ -373,6 +380,8 @@ struct Sidebar::priv
void jump_to_object(ObjectDataViewModelNode* item);
void can_search();
+ void sync_extruder_list();
+
#ifdef _WIN32
wxString btn_reslice_tip;
void show_rich_tip(const wxString& tooltip, wxButton* btn);
@@ -589,6 +598,99 @@ static struct DynamicFilamentList : DynamicList
}
} dynamic_filament_list;
+class AMSCountPopupWindow : public PopupWindow
+{
+public:
+ AMSCountPopupWindow(wxWindow * parent, wxStaticText *text, int index)
+ : PopupWindow(parent, wxBORDER_SIMPLE)
+ {
+ auto msg = new wxStaticText(this, wxID_ANY, _L("Please set the number of ams installed on the this extrusion head."));
+ msg->SetFont(Label::Body_14);
+ msg->Wrap(FromDIP(240));
+ auto img4 = new ScalableButton(this, wxID_ANY, "ams_4_tray", {}, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, false, 44);
+ auto img1 = new ScalableButton(this, wxID_ANY, "ams_1_tray", {}, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, false, 44);
+ auto txt4 = new wxStaticText(this, wxID_ANY, _L("AMS(4 colors)"));
+ txt4->SetFont(Label::Body_14);
+ auto txt1 = new wxStaticText(this, wxID_ANY, _L("AMS(single color)"));
+ txt1->SetFont(Label::Body_14);
+ int ams4 = 0, ams1 = 0;
+ GetAMSCount(index, ams4, ams1);
+ auto val4 = new SpinInput(this, {}, {}, wxDefaultPosition, {FromDIP(60), -1}, 0, 0, 4, ams4);
+ auto val1 = new SpinInput(this, {}, {}, wxDefaultPosition, {FromDIP(60), -1}, 0, 0, 8, ams1);
+ auto event_handler = [index, val4, val1, text](auto &evt) {
+ SetAMSCount(index, val4->GetValue(), val1->GetValue());
+ UpdateAMSCount(index, text);
+ };
+ val4->Bind(wxEVT_SPINCTRL, event_handler);
+ val1->Bind(wxEVT_SPINCTRL, event_handler);
+
+ wxSizer * sizer = new wxBoxSizer(wxVERTICAL);
+ sizer->Add(msg, 0, wxTOP | wxLEFT | wxRIGHT, FromDIP(10));
+ wxSizer * sizer2 = new wxBoxSizer(wxHORIZONTAL);
+ wxSizer *sizer21 = new wxBoxSizer(wxVERTICAL);
+ sizer21->Add(img4, 0, wxALIGN_CENTRE_HORIZONTAL);
+ sizer21->Add(txt4, 0, wxTOP | wxALIGN_CENTRE_HORIZONTAL, FromDIP(10));
+ sizer21->Add(val4, 0, wxTOP | wxALIGN_CENTRE_HORIZONTAL, FromDIP(10));
+ sizer2->Add(sizer21, 1);
+ wxSizer *sizer22 = new wxBoxSizer(wxVERTICAL);
+ sizer22->Add(img1, 0, wxALIGN_CENTRE_HORIZONTAL);
+ sizer22->Add(txt1, 0, wxTOP | wxALIGN_CENTRE_HORIZONTAL, FromDIP(10));
+ sizer22->Add(val1, 0, wxTOP | wxALIGN_CENTRE_HORIZONTAL, FromDIP(10));
+ sizer2->Add(sizer22, 1);
+ sizer->Add(sizer2, 0, wxTOP | wxBOTTOM | wxLEFT | wxRIGHT | wxEXPAND, FromDIP(10));
+ SetSizer(sizer);
+
+ Layout();
+ Fit();
+
+ SetBackgroundColour(*wxWHITE);
+ wxGetApp().UpdateDarkUIWin(this);
+ }
+
+ static void SetAMSCount(int index, int ams4, int ams1)
+ {
+ auto count_str = wxGetApp().app_config->get("preset", "ams_count");
+ std::vector counts;
+ boost::algorithm::split(counts, count_str, boost::algorithm::is_any_of("|"));
+ counts.resize(2);
+ counts[index] = (boost::format("%d/%d") % ams4 % ams1).str();
+ wxGetApp().app_config->set("preset", "ams_count", boost::algorithm::join(counts, "|"));
+ }
+
+ static void GetAMSCount(int index, int & ams4, int & ams1)
+ {
+ auto count_str = wxGetApp().app_config->get("preset", "ams_count");
+ std::vector counts;
+ boost::algorithm::split(counts, count_str, boost::algorithm::is_any_of("|"));
+ counts.resize(2);
+ std::vector counts2;
+ boost::algorithm::split(counts2, counts[index], boost::algorithm::is_any_of("/"));
+ counts2.resize(2);
+ ams4 = std::atoi(counts2[0].c_str());
+ ams1 = std::atoi(counts2[1].c_str());
+ }
+
+ static void UpdateAMSCount(int index, wxStaticText *text)
+ {
+ auto count_str = wxGetApp().app_config->get("preset", "ams_count");
+ std::vector counts;
+ boost::algorithm::split(counts, count_str, boost::algorithm::is_any_of("|"));
+ counts.resize(2);
+ text->SetLabel(from_u8(counts[index]));
+ }
+};
+
+void Sidebar::priv::sync_extruder_list()
+{
+ auto printer_tab = dynamic_cast(wxGetApp().get_tab(Preset::TYPE_PRINTER));
+ printer_tab->set_extruder_volume_type(0, NozzleVolumeType::nvtBigTraffic);
+ printer_tab->set_extruder_volume_type(1, NozzleVolumeType::nvtNormal);
+ AMSCountPopupWindow::SetAMSCount(0, 0, 0);
+ AMSCountPopupWindow::SetAMSCount(1, 1, 1);
+ AMSCountPopupWindow::UpdateAMSCount(0, m_left_ams_count);
+ AMSCountPopupWindow::UpdateAMSCount(1, m_right_ams_count);
+}
+
Sidebar::Sidebar(Plater *parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(42 * wxGetApp().em_unit(), -1)), p(new priv(parent))
{
@@ -654,11 +756,20 @@ Sidebar::Sidebar(Plater *parent)
m_soft_first_start = false;
wxGetApp().run_wizard(ConfigWizard::RR_USER, ConfigWizard::SP_PRINTERS);
});
+ auto extruder_btn = new ScalableButton(p->m_panel_printer_title, wxID_ANY, "ams_fila_sync", wxEmptyString, wxDefaultSize, wxDefaultPosition,
+ wxBU_EXACTFIT | wxNO_BORDER, false, 18);
+ extruder_btn->SetToolTip(_L("Synchronize nozzle information and the number of AMS"));
+ extruder_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) {
+ p->sync_extruder_list();
+ });
+ p->m_extruder_sync = extruder_btn;
wxBoxSizer* h_sizer_title = new wxBoxSizer(wxHORIZONTAL);
h_sizer_title->Add(p->m_printer_icon, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, em);
h_sizer_title->Add(p->m_text_printer_settings, 0, wxALIGN_CENTER);
h_sizer_title->AddStretchSpacer();
+ h_sizer_title->Add(p->m_extruder_sync, 0, wxALIGN_CENTER);
+ h_sizer_title->Add(15 * em / 10, 0, 0, 0, 0);
h_sizer_title->Add(p->m_printer_setting, 0, wxALIGN_CENTER);
h_sizer_title->Add(15 * em / 10, 0, 0, 0, 0);
h_sizer_title->SetMinSize(-1, 3 * em);
@@ -718,11 +829,11 @@ Sidebar::Sidebar(Plater *parent)
wxBoxSizer* hsizer_printer = new wxBoxSizer(wxHORIZONTAL);
vsizer_printer->AddSpacer(FromDIP(16));
- hsizer_printer->Add(combo_printer, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3));
+ hsizer_printer->Add(combo_printer, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(10));
hsizer_printer->Add(edit_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3));
hsizer_printer->Add(FromDIP(8), 0, 0, 0, 0);
hsizer_printer->Add(connection_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3));
- hsizer_printer->Add(FromDIP(8), 0, 0, 0, 0);
+ hsizer_printer->Add(FromDIP(10), 0, 0, 0, 0);
vsizer_printer->Add(hsizer_printer, 0, wxEXPAND, 0);
// Bed type selection
@@ -731,11 +842,11 @@ Sidebar::Sidebar(Plater *parent)
//bed_type_title->SetBackgroundColour();
bed_type_title->Wrap(-1);
bed_type_title->SetFont(Label::Body_14);
- m_bed_type_list = new ComboBox(p->m_panel_printer_content, wxID_ANY, wxString(""), wxDefaultPosition, {-1, FromDIP(30)}, 0, nullptr, wxCB_READONLY);
+ p->m_bed_type_list = new ComboBox(p->m_panel_printer_content, wxID_ANY, wxString(""), wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY);
const ConfigOptionDef* bed_type_def = print_config_def.get("curr_bed_type");
if (bed_type_def && bed_type_def->enum_keys_map) {
for (auto item : bed_type_def->enum_labels) {
- m_bed_type_list->AppendString(_L(item));
+ p->m_bed_type_list->AppendString(_L(item));
}
}
@@ -767,11 +878,10 @@ Sidebar::Sidebar(Plater *parent)
}
int bed_type_idx = bed_type_value - 1;
- m_bed_type_list->Select(bed_type_idx);
- bed_type_sizer->Add(bed_type_title, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, FromDIP(10));
- bed_type_sizer->Add(m_bed_type_list, 1, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(10));
+ p->m_bed_type_list->Select(bed_type_idx);
+ bed_type_sizer->Add(bed_type_title, 1, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, FromDIP(10));
+ bed_type_sizer->Add(p->m_bed_type_list, 4, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(10));
vsizer_printer->Add(bed_type_sizer, 0, wxEXPAND | wxTOP, FromDIP(5));
- vsizer_printer->AddSpacer(FromDIP(16));
auto& project_config = wxGetApp().preset_bundle->project_config;
/*const t_config_enum_values* keys_map = print_config_def.get("curr_bed_type")->enum_keys_map;
@@ -783,6 +893,67 @@ Sidebar::Sidebar(Plater *parent)
BedType bed_type = (BedType)bed_type_value;
project_config.set_key_value("curr_bed_type", new ConfigOptionEnum(bed_type));
+ // Dual Extruder Types (Begin)
+ p->m_dual_extruder_sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ auto add_extruder = [this](int index, wxString const & title) {
+ wxStaticBox * static_box = new wxStaticBox(p->m_panel_printer_content, wxID_ANY, title);
+ static_box->SetFont(Label::Body_10);
+ static_box->SetForegroundColour("#909090");
+ wxStaticBoxSizer *static_box_sizer = new wxStaticBoxSizer(static_box, wxVERTICAL);
+ // Nozzle
+ wxBoxSizer * nozzle_sizer = new wxBoxSizer(wxHORIZONTAL);
+ wxStaticText * nozzle_title = new wxStaticText(static_box, wxID_ANY, _L("Nozzle"));
+ nozzle_title->SetFont(Label::Body_14);
+ nozzle_title->SetForegroundColour("#262E30");
+ auto nozzle_type_list = new ComboBox(static_box, wxID_ANY, wxString(""), wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY);
+ nozzle_type_list->Bind(wxEVT_COMBOBOX, [this, index, nozzle_type_list](wxCommandEvent &evt) {
+ auto printer_tab = dynamic_cast(wxGetApp().get_tab(Preset::TYPE_PRINTER));
+ printer_tab->set_extruder_volume_type(index, NozzleVolumeType(intptr_t(nozzle_type_list->GetClientData(evt.GetInt()))));
+ });
+ nozzle_sizer->Add(nozzle_title, 2, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(10));
+ nozzle_sizer->Add(nozzle_type_list, 3, wxLEFT | wxEXPAND, FromDIP(10));
+ static_box_sizer->Add(nozzle_sizer, 0, wxTOP | wxEXPAND, FromDIP(5));
+ // AMS count
+ wxBoxSizer * ams_count_sizer = new wxBoxSizer(wxHORIZONTAL);
+ wxStaticText *ams_count_title = new wxStaticText(static_box, wxID_ANY, _L("AMS"));
+ ams_count_title->SetFont(Label::Body_14);
+ ams_count_title->SetForegroundColour("#262E30");
+ auto ams_count_text = new wxStaticText(static_box, wxID_ANY, wxString("1/1"));
+ ams_count_text->SetFont(Label::Body_14);
+ ams_count_text->SetForegroundColour("#262E30");
+ AMSCountPopupWindow::UpdateAMSCount(index, ams_count_text);
+ auto ams_count_edit = new ScalableButton(static_box, wxID_ANY, "edit");
+ ams_count_edit->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this, index, ams_count_text](auto &evt) {
+ PopupWindow *window = new AMSCountPopupWindow(ams_count_text, ams_count_text, index);
+ auto pos = ams_count_text->ClientToScreen({0, 0});
+ auto size = ams_count_text->GetSize();
+ size.SetWidth(size.GetWidth() + FromDIP(10));
+ window->Position(pos, size);
+ window->Popup();
+ });
+ ams_count_edit->SetBackgroundColour(*wxWHITE);
+ ams_count_sizer->Add(ams_count_title, 2, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(10));
+ ams_count_sizer->Add(ams_count_text, 1, wxLEFT | wxEXPAND, FromDIP(10));
+ ams_count_sizer->Add(ams_count_edit, 2, wxLEFT | wxEXPAND, FromDIP(10));
+ static_box_sizer->Add(ams_count_sizer, 0, wxTOP | wxBOTTOM | wxEXPAND, FromDIP(5));
+ p->m_dual_extruder_sizer->Add(static_box_sizer, 1, wxEXPAND);
+ return std::make_pair(nozzle_type_list, ams_count_text);
+ };
+ p->m_dual_extruder_sizer->Add(FromDIP(10), 0);
+ auto left_extruder = add_extruder(0, _L("Left Extruder"));
+ p->m_left_extruder_list = left_extruder.first;
+ p->m_left_ams_count = left_extruder.second;
+ p->m_dual_extruder_sizer->Add(FromDIP(2), 0);
+ auto right_extruder = add_extruder(1, _L("Right Extruder"));
+ p->m_right_extruder_list = right_extruder.first;
+ p->m_right_ams_count = right_extruder.second;
+ p->m_dual_extruder_sizer->Add(FromDIP(10), 0);
+
+ vsizer_printer->Add(p->m_dual_extruder_sizer, 0, wxEXPAND | wxTOP, FromDIP(5));
+ // Dual Extruder Types (End)
+
+ vsizer_printer->AddSpacer(FromDIP(16));
p->m_panel_printer_content->SetSizer(vsizer_printer);
p->m_panel_printer_content->Layout();
scrolled_sizer->Add(p->m_panel_printer_content, 0, wxEXPAND, 0);
@@ -1158,7 +1329,7 @@ void Sidebar::set_bed_by_curr_bed_type(AppConfig *config) {
} catch (...) {
}
bed_type_idx = bed_type_value - 1;
- m_bed_type_list->SelectAndNotify(bed_type_idx);
+ p->m_bed_type_list->SelectAndNotify(bed_type_idx);
} else {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":error:curr_bed_type is empty";
}
@@ -1212,7 +1383,7 @@ void Sidebar::update_all_preset_comboboxes()
} else {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":error:AppConfig is nullptr";
}
- m_bed_type_list->Enable();
+ p->m_bed_type_list->Enable();
} else {
connection_btn->Show();
ams_btn->Hide();
@@ -1235,8 +1406,8 @@ void Sidebar::update_all_preset_comboboxes()
p_mainframe->load_printer_url(url);
}
- m_bed_type_list->SelectAndNotify(btPEI - 1);
- m_bed_type_list->Disable();
+ p->m_bed_type_list->SelectAndNotify(btPEI - 1);
+ p->m_bed_type_list->Disable();
}
// Update the print choosers to only contain the compatible presets, update the dirty flags.
@@ -1331,6 +1502,31 @@ void Sidebar::update_presets(Preset::Type preset_type)
else
wxGetApp().plater()->get_current_canvas3D()->get_arrange_settings().align_to_y_axis = false;
+ // Update dual extrudes
+ auto extruder_variants = printer_preset.config.option("extruder_variant_list");
+ p->m_dual_extruder_sizer->Show(extruder_variants->size() == 2);
+ if (extruder_variants->size() == 2) {
+ auto extruders_def = printer_preset.config.def()->get("extruder_type");
+ auto extruders = printer_preset.config.option("extruder_type");
+ auto nozzle_volumes_def = printer_preset.config.def()->get("nozzle_volume_type");
+ auto nozzle_volumes = printer_preset.config.option("nozzle_volume_type");
+ auto update_extruder_variant = [extruders_def, extruders, nozzle_volumes_def, nozzle_volumes, extruder_variants](ComboBox &box, int index) {
+ box.Clear();
+ auto extruder = extruders_def->enum_labels[extruders->values[index]];
+ int select = -1;
+ for (size_t i = 0; i < nozzle_volumes_def->enum_labels.size(); ++i) {
+ if (boost::algorithm::contains(extruder_variants->values[index], extruder + " " + nozzle_volumes_def->enum_labels[i])) {
+ if (nozzle_volumes->values[index] == i)
+ select = box.GetCount();
+ box.Append(_L(nozzle_volumes_def->enum_labels[i], {}, (void*)i));
+ }
+ }
+ box.SetSelection(select);
+ };
+ update_extruder_variant(*p->m_left_extruder_list, 0);
+ update_extruder_variant(*p->m_right_extruder_list, 1);
+ }
+
break;
}
@@ -1379,7 +1575,7 @@ bool Sidebar::set_bed_type(const std::string &bed_type_name)
auto bed_type_keys = print_config_def.get("curr_bed_type")->enum_values;
for (size_t i = 0; i < bed_type_keys.size(); i++) {
if (bed_type_name == bed_type_keys[i]) {
- m_bed_type_list->SelectAndNotify(i);
+ p->m_bed_type_list->SelectAndNotify(i);
return true;
}
}
@@ -1412,7 +1608,7 @@ bool Sidebar::use_default_bed_type(bool is_bbl_preset)
if (is_bbl_preset && pm && pm->default_bed_type.size() > 0) {
return set_bed_type(pm->default_bed_type);
}
- int selection = m_bed_type_list->GetSelection();
+ int selection = p->m_bed_type_list->GetSelection();
std::string bed_type_name = print_config_def.get("curr_bed_type")->enum_values[selection];
save_bed_type_to_config(bed_type_name);
return false;
@@ -1444,8 +1640,8 @@ void Sidebar::msw_rescale()
p->m_bpButton_set_filament->msw_rescale();
p->m_flushing_volume_btn->Rescale();
//BBS
- m_bed_type_list->Rescale();
- m_bed_type_list->SetMinSize({-1, 3 * wxGetApp().em_unit()});
+ p->m_bed_type_list->Rescale();
+ p->m_bed_type_list->SetMinSize({-1, 3 * wxGetApp().em_unit()});
#if 0
if (p->mode_sizer)
p->mode_sizer->msw_rescale();
@@ -1658,8 +1854,7 @@ void Sidebar::on_bed_type_change(BedType bed_type)
{
// btDefault option is not included in global bed type setting
int sel_idx = (int)bed_type - 1;
- if (m_bed_type_list != nullptr)
- m_bed_type_list->SetSelection(sel_idx);
+ if (p->m_bed_type_list != nullptr) p->m_bed_type_list->SetSelection(sel_idx);
}
std::map Sidebar::build_filament_ams_list(MachineObject* obj)
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index fc6d502e8..424a70b4c 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -192,7 +192,6 @@ private:
std::unique_ptr p;
wxBoxSizer* m_scrolled_sizer = nullptr;
- ComboBox* m_bed_type_list = nullptr;
ScalableButton* connection_btn = nullptr;
ScalableButton* ams_btn = nullptr;
bool m_soft_first_start {true };
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index a4466b049..8dd047e76 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -5506,6 +5506,8 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep
return sizer;
}
+void TabPrinter::set_extruder_volume_type(int extruder_id, NozzleVolumeType type) {}
+
// Return a callback to create a TabPrinter widget to edit bed shape
wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent)
{
diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp
index 6e1bb8a42..ce5114a61 100644
--- a/src/slic3r/GUI/Tab.hpp
+++ b/src/slic3r/GUI/Tab.hpp
@@ -615,6 +615,8 @@ public:
void msw_rescale() override;
bool supports_printer_technology(const PrinterTechnology /* tech */) const override { return true; }
+ void set_extruder_volume_type(int extruder_id, NozzleVolumeType type);
+
wxSizer* create_bed_shape_widget(wxWindow* parent);
void cache_extruder_cnt();
bool apply_extruder_cnt_from_cache();