diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index acb5c89e3d..fceaeba3bd 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -692,11 +692,60 @@ void Preview::update_double_slider(const std::vector& layers_z, bool kee bool color_print_enable = (wxGetApp().plater()->printer_technology() == ptFFF); m_slider->EnableTickManipulation(color_print_enable); - // Detect and set manipulation mode for double slider - m_slider->SetManipulationMode( wxGetApp().extruders_edited_cnt() == 1 ? DoubleSlider::mmSingleExtruder : - wxGetApp().plater()->is_one_extruder_printed_model() ? DoubleSlider::mmMultiAsSingle : - DoubleSlider::mmMultiExtruder); + update_double_slider_mode(); +} + +void Preview::update_double_slider_mode() +{ + // true -> single-extruder printer profile OR + // multi-extruder printer profile , but whole model is printed by only one extruder + // false -> multi-extruder printer profile , and model is printed by several extruders + bool one_extruder_printed_model = true; + + // extruder used for whole model for multi-extruder printer profile + int only_extruder = -1; + + if (wxGetApp().extruders_edited_cnt() > 1) + { + const ModelObjectPtrs& objects = wxGetApp().plater()->model().objects; + + // check if whole model uses just only one extruder + if (!objects.empty()) + { + const int extruder = objects[0]->config.has("extruder") ? + objects[0]->config.option("extruder")->getInt() : 0; + + auto is_one_extruder_printed_model = [objects, extruder]() + { + for (ModelObject* object : objects) + { + if (object->config.has("extruder") && + object->config.option("extruder")->getInt() != extruder) + return false; + + if (object->volumes.size() > 1) + for (ModelVolume* volume : object->volumes) + if (volume->config.has("extruder") && + volume->config.option("extruder")->getInt() != extruder) + return false; + + for (const auto& range : object->layer_config_ranges) + if (range.second.has("extruder") && + range.second.option("extruder")->getInt() != extruder) + return false; + } + return true; + }; + + if (is_one_extruder_printed_model()) + only_extruder = extruder; + else + one_extruder_printed_model = false; + } + } + + m_slider->SetModeAndOnlyExtruder(one_extruder_printed_model, only_extruder); } void Preview::reset_double_slider() diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 92ec15b22b..ae93e2ff05 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -157,8 +157,9 @@ private: void create_double_slider(); void check_slider_values(std::vector &ticks_from_model, const std::vector &layers_z); - void update_double_slider(const std::vector& layers_z, bool keep_z_range = false); void reset_double_slider(); + void update_double_slider(const std::vector& layers_z, bool keep_z_range = false); + void update_double_slider_mode(); // update DoubleSlider after keyDown in canvas void update_double_slider_from_canvas(wxKeyEvent& event); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 01241bd8f9..2c07425594 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5358,38 +5358,6 @@ bool Plater::is_export_gcode_scheduled() const return p->background_process.is_export_scheduled(); } -bool Plater::is_one_extruder_printed_model() -{ - if (wxGetApp().extruders_edited_cnt() == 1) - return true; - - // check if model use just one extruder - const ModelObjectPtrs& objects = p->model.objects; - if (!objects.empty()) - { - const size_t extruder = objects[0]->config.has("extruder") ? - objects[0]->config.option("extruder")->getInt() : 0; - for (ModelObject* object : objects) - { - if (object->config.has("extruder") && - object->config.option("extruder")->getInt() != extruder) - return false; - - for (ModelVolume* volume : object->volumes) - if (volume->config.has("extruder") && - volume->config.option("extruder")->getInt() != extruder) - return false; - - for (const auto& range : object->layer_config_ranges) - if (range.second.has("extruder") && - range.second.option("extruder")->getInt() != extruder) - return false; - } - } - - return true; -} - int Plater::get_selected_object_idx() { return p->get_selected_object_idx(); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 2c7e13e45a..4793977058 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -234,7 +234,6 @@ public: void set_project_filename(const wxString& filename); bool is_export_gcode_scheduled() const; - bool is_one_extruder_printed_model(); int get_selected_object_idx(); bool is_single_full_object_selection() const; diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 8ccf605f57..a831f32bb6 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -2883,7 +2883,9 @@ bool DoubleSlider::get_color_for_tick(wxColour& color, std::set::cons return std::min(extruders_cnt - 1, std::max(current_extruder - 1, 0)); }; - auto get_color_idx_for_color_change = [get_m600_color_idx](const std::set& ticks, std::set::const_iterator it) + const int extruder = std::max(1, m_only_extruder); + + auto get_color_idx_for_color_change = [get_m600_color_idx, extruder](const std::set& ticks, std::set::const_iterator it) { auto it_n = it; bool is_tool_change = false; @@ -2896,7 +2898,7 @@ bool DoubleSlider::get_color_for_tick(wxColour& color, std::set::cons break; } } - if (!is_tool_change && it->extruder == 0) // use correct extruder number instead of 0 + if (!is_tool_change && it->extruder == extruder) // use correct extruder number instead of 0 return get_m600_color_idx(ticks, it); return -1; @@ -2943,9 +2945,9 @@ void DoubleSlider::draw_colored_band(wxDC& dc) const std::vector& colors = Slic3r::GUI::wxGetApp().plater()->get_colors_for_color_print(); - const wxColour bg_clr = GetParent()->GetBackgroundColour(); - - wxColour clr = m_ticks.empty() || m_mode == mmMultiExtruder ? bg_clr : wxColour(colors[0]); + wxColour clr = m_ticks.empty() || m_mode == mmMultiExtruder ? + GetParent()->GetBackgroundColour() : + wxColour(colors[m_mode==mmMultiAsSingle ? std::max(m_only_extruder - 1, 0) : 0]); draw_band(dc, clr, main_band); if (m_ticks.empty() || m_mode == mmMultiExtruder) @@ -2972,7 +2974,7 @@ void DoubleSlider::draw_colored_band(wxDC& dc) ++tick_it; continue; } - + draw_band(dc, clr, main_band); ++tick_it; } @@ -3268,6 +3270,62 @@ void DoubleSlider::OnMotion(wxMouseEvent& event) } } +void DoubleSlider::append_change_extruder_menu_item(wxMenu* menu) +{ + const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt(); + if (extruders_cnt > 1) + { + const int initial_extruder = std::max(1 , get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value)); + + wxMenu* change_extruder_menu = new wxMenu(); + + for (int i = 1; i <= extruders_cnt; i++) + { + const wxString item_name = wxString::Format(_(L("Extruder %d")), i); + + if (m_mode == mmMultiAsSingle) + append_menu_radio_item(change_extruder_menu, wxID_ANY, item_name, "", + [this, i](wxCommandEvent&) { change_extruder(i); }, menu)->Check(i == initial_extruder); + } + + const wxString change_extruder_menu_name = m_mode == mmMultiAsSingle ? _(L("Change extruder")) : _(L("Change extruder (N/A)")); + + wxMenuItem* change_extruder_menu_item = menu->AppendSubMenu(change_extruder_menu, change_extruder_menu_name, _(L("Use another extruder"))); + change_extruder_menu_item->SetBitmap(create_scaled_bitmap(this, "change_extruder")); + + Slic3r::GUI::wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this, change_extruder_menu_item](wxUpdateUIEvent& evt) { + enable_menu_item(evt, [this]() {return m_mode == mmMultiAsSingle; }, change_extruder_menu_item, this); }, + change_extruder_menu_item->GetId()); + } +} + +void DoubleSlider::append_add_color_change_menu_item(wxMenu* menu) +{ + const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt(); + if (extruders_cnt > 1) + { + std::set used_extruders_for_tick = get_used_extruders_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value); + + wxMenu* add_color_change_menu = new wxMenu(); + + for (int i = 1; i <= extruders_cnt; i++) + { + const bool is_used_extruder = used_extruders_for_tick.empty() ? true : // #ys_FIXME till used_extruders_for_tick doesn't filled correct for mmMultiExtruder + used_extruders_for_tick.find(i) != used_extruders_for_tick.end(); + const wxString item_name = wxString::Format(_(L("Extruder %d")), i) + + (is_used_extruder ? "" : " (" + _(L("N/A")) + ")"); + + append_menu_item(add_color_change_menu, wxID_ANY, item_name, "", + [this, i](wxCommandEvent&) { add_code(Slic3r::ColorChangeCode, i); }, "", menu, + [is_used_extruder]() { return is_used_extruder; }, Slic3r::GUI::wxGetApp().plater()); + } + + const wxString menu_name = from_u8((boost::format(_utf8(L("Add color change (%1%) for:"))) % Slic3r::ColorChangeCode).str()); + wxMenuItem* add_color_change_menu_item = menu->AppendSubMenu(add_color_change_menu, menu_name, ""); + add_color_change_menu_item->SetBitmap(create_scaled_bitmap(nullptr, "colorchange_add_m")); + } +} + void DoubleSlider::OnLeftUp(wxMouseEvent& event) { if (!HasCapture()) @@ -3281,46 +3339,14 @@ void DoubleSlider::OnLeftUp(wxMouseEvent& event) add_code(Slic3r::ColorChangeCode); else { - const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt(); - if (extruders_cnt > 1) - { - wxMenu menu; - wxMenu* sub_menu = new wxMenu(); - wxString sub_menu_name = _(L("Change extruder")); - std::string menu_icon_name = "change_extruder"; + wxMenu menu; - if (m_mode == mmMultiAsSingle) - { - int initial_extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value); - if (initial_extruder == 0) - initial_extruder = 1; + if (m_mode == mmMultiAsSingle) + append_change_extruder_menu_item(&menu); + else + append_add_color_change_menu_item(&menu); - for (int i = /*0*/1; i <= extruders_cnt; i++) { - const wxString item_name = i == 0 ? _(L("Default")) : wxString::Format(_(L("Extruder %d")), i); - - append_menu_radio_item(sub_menu, wxID_ANY, item_name, "", - [this, i](wxCommandEvent&) { change_extruder(i); }, &menu)->Check(i == initial_extruder); - } - } - else - { - for (int i = 1; i <= extruders_cnt; i++) { - const wxString item_name = wxString::Format(_(L("Extruder %d")), i); - - append_menu_item(sub_menu, wxID_ANY, item_name, "", - [this, i](wxCommandEvent&) { add_code(Slic3r::ColorChangeCode, i); }, "", &menu, - [this]() {return true; }, this); - } - - sub_menu_name = from_u8((boost::format(_utf8(L("Add color change (%1%) for:"))) % Slic3r::ColorChangeCode).str()); - menu_icon_name = "colorchange_add_m"; - } - - wxMenuItem* sub_menu_item = menu.AppendSubMenu(sub_menu, sub_menu_name, ""); - sub_menu_item->SetBitmap(create_scaled_bitmap(this, menu_icon_name)); - - Slic3r::GUI::wxGetApp().plater()->PopupMenu(&menu); - } + Slic3r::GUI::wxGetApp().plater()->PopupMenu(&menu); } m_show_context_menu = false; @@ -3525,8 +3551,9 @@ void DoubleSlider::OnRightDown(wxMouseEvent& event) int DoubleSlider::get_extruder_for_tick(int tick) { + int default_initial_extruder = m_mode == mmMultiAsSingle ? m_only_extruder : 0; if (m_ticks.empty()) - return 0; + return default_initial_extruder; auto it = m_ticks.lower_bound(TICK_CODE{tick}); while (it != m_ticks.begin()) { @@ -3535,7 +3562,40 @@ int DoubleSlider::get_extruder_for_tick(int tick) return it->extruder; } - return 0; + return default_initial_extruder; +} + +std::set DoubleSlider::get_used_extruders_for_tick(int tick) +{ + if (m_mode == mmMultiExtruder) + return {}; // #ys_FIXME: correct fill used_extruders_for_tick for mmMultiExtruder + + const int default_initial_extruder = m_mode == mmMultiAsSingle ? std::max(m_only_extruder, 1) : 1; + if (m_ticks.empty()) + return {default_initial_extruder}; + + std::set used_extruders; + + auto it = m_ticks.lower_bound(TICK_CODE{tick}); + while (it != m_ticks.begin()) { + --it; + if(it->gcode == Slic3r::ExtruderChangeCode) + { + used_extruders.emplace(it->extruder); + break; + } + } + if (it == m_ticks.begin()) + used_extruders.emplace(default_initial_extruder); + ++it; + + while (it != m_ticks.end()) { + if(it->gcode == Slic3r::ExtruderChangeCode) + used_extruders.emplace(it->extruder); + ++it; + } + + return used_extruders; } void DoubleSlider::OnRightUp(wxMouseEvent& event) @@ -3554,42 +3614,8 @@ void DoubleSlider::OnRightUp(wxMouseEvent& event) [](){return true;}, this); else { - const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt(); - if (extruders_cnt > 1) - { - int initial_extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value); - if (initial_extruder == 0) - initial_extruder = 1; - - wxMenu* change_extruder_menu = new wxMenu(); - wxMenu* add_color_change_menu = new wxMenu(); - - for (int i = 1; i <= extruders_cnt; i++) { - const wxString item_name = wxString::Format(_(L("Extruder %d")), i); - - if (m_mode == mmMultiAsSingle) - append_menu_radio_item(change_extruder_menu, wxID_ANY, item_name, "", - [this, i](wxCommandEvent&) { change_extruder(i); }, &menu)->Check(i == initial_extruder); - - append_menu_item(add_color_change_menu, wxID_ANY, item_name, "", - [this, i](wxCommandEvent&) { add_code(Slic3r::ColorChangeCode, i); }, "", &menu, - [](){return true;}, this); - } - - const wxString change_extruder_menu_name = m_mode == mmMultiAsSingle ? _(L("Change extruder")) : _(L("Change extruder (N/A)")); - - wxMenuItem* change_extruder_menu_item = menu.AppendSubMenu(change_extruder_menu, change_extruder_menu_name, _(L("Use another extruder"))); - change_extruder_menu_item->SetBitmap(create_scaled_bitmap(nullptr, "change_extruder")); - - ManipulationMode mode = m_mode; - Slic3r::GUI::wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this, mode, change_extruder_menu_item](wxUpdateUIEvent& evt) { - enable_menu_item(evt, [this](){return m_mode == mmMultiAsSingle;}, change_extruder_menu_item, this); }, - change_extruder_menu_item->GetId()); - - const wxString menu_name = from_u8((boost::format(_utf8(L("Add color change (%1%) for:"))) % Slic3r::ColorChangeCode).str()); - wxMenuItem* add_color_change_menu_item = menu.AppendSubMenu(add_color_change_menu, menu_name, ""); - add_color_change_menu_item->SetBitmap(create_scaled_bitmap(nullptr, "colorchange_add_m")); - } + append_change_extruder_menu_item(&menu); + append_add_color_change_menu_item(&menu); } append_menu_item(&menu, wxID_ANY, _(L("Add pause print")) + " (M601)", "", diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 87cc922cf7..35357cea48 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -831,6 +831,14 @@ public: void SetManipulationMode(ManipulationMode mode) { m_mode = mode; } ManipulationMode GetManipulationMode() const { return m_mode; } + void SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder) + { + m_mode = !is_one_extruder_printed_model ? mmMultiExtruder : + only_extruder < 0 ? mmSingleExtruder : + mmMultiAsSingle; + m_only_extruder = only_extruder; + } + bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; } bool is_one_layer() const { return m_is_one_layer; } bool is_lower_at_min() const { return m_lower_value == m_min_value; } @@ -848,7 +856,6 @@ public: void OnKeyUp(wxKeyEvent &event); void OnChar(wxKeyEvent &event); void OnRightDown(wxMouseEvent& event); - int get_extruder_for_tick(int tick); void OnRightUp(wxMouseEvent& event); void add_code(std::string code, int selected_extruder = -1); void edit_tick(); @@ -906,6 +913,12 @@ protected: bool get_color_for_tick( wxColour& color, std::set::const_iterator tick_it, const std::vector& colors) const; + int get_extruder_for_tick(int tick); + std::set get_used_extruders_for_tick(int tick); + + + void append_change_extruder_menu_item(wxMenu*); + void append_add_color_change_menu_item(wxMenu*); private: bool is_osx { false }; @@ -926,7 +939,7 @@ private: ScalableBitmap m_bmp_one_layer_unlock_off; ScalableBitmap m_bmp_revert; ScalableBitmap m_bmp_cog; - SelectedSlider m_selection; + SelectedSlider m_selection; bool m_is_left_down = false; bool m_is_right_down = false; bool m_is_one_layer = false; @@ -941,6 +954,7 @@ private: ManipulationMode m_mode = mmSingleExtruder; std::string m_custom_gcode = ""; std::string m_pause_print_msg; + int m_only_extruder = -1; wxRect m_rect_lower_thumb; wxRect m_rect_higher_thumb;