From 07c1c3d1dc9aade0b95fa570314205ee8ee35481 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 8 Jan 2020 15:23:46 +0100 Subject: [PATCH 1/8] Fixed update of "Cost" field in "Sliced Info" box after a change of any material's options ("bottle_cost", "bottle_volume", "bottle_weight", "material_density") --- src/slic3r/GUI/Plater.cpp | 4 ++-- src/slic3r/GUI/Tab.cpp | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b0fb3f0e68..2c07425594 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1192,9 +1192,9 @@ void Sidebar::update_sliced_info_sizer() { double material_cost = cfg->option("bottle_cost")->getFloat() / cfg->option("bottle_volume")->getFloat(); - str_total_cost = wxString::Format("%.2f", material_cost*(ps.objects_used_material + ps.support_used_material) / 1000); + str_total_cost = wxString::Format("%.3f", material_cost*(ps.objects_used_material + ps.support_used_material) / 1000); } - p->sliced_info->SetTextAndShow(siCost, str_total_cost); + p->sliced_info->SetTextAndShow(siCost, str_total_cost, "Cost"); wxString t_est = std::isnan(ps.estimated_print_time) ? "N/A" : get_time_dhms(float(ps.estimated_print_time)); p->sliced_info->SetTextAndShow(siEstimatedTime, t_est, _(L("Estimated printing time")) + " :"); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 353e822e3d..c518ede80d 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3448,7 +3448,7 @@ void TabSLAMaterial::build() new_conf.set_key_value("bottle_weight", new ConfigOptionFloat(new_bottle_weight)); } if (opt_key == "bottle_weight") { - double new_bottle_volume = boost::any_cast(value)/(new_conf.option("material_density")->getFloat() * 1000); + double new_bottle_volume = boost::any_cast(value)/new_conf.option("material_density")->getFloat() * 1000; new_conf.set_key_value("bottle_volume", new ConfigOptionFloat(new_bottle_volume)); } if (opt_key == "material_density") { @@ -3459,12 +3459,10 @@ void TabSLAMaterial::build() load_config(new_conf); update_dirty(); - on_value_change(opt_key, value); - if (opt_key == "bottle_volume" || opt_key == "bottle_cost") { - wxGetApp().sidebar().update_sliced_info_sizer(); - wxGetApp().sidebar().Layout(); - } + // Change of any from those options influences for an update of "Sliced Info" + wxGetApp().sidebar().update_sliced_info_sizer(); + wxGetApp().sidebar().Layout(); }; optgroup = page->new_optgroup(_(L("Layers"))); From fb65e3152f12faf6d515e8e1c184e00c9a42758b Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 8 Jan 2020 15:26:01 +0100 Subject: [PATCH 2/8] DoubleSlider modes(states) are extended and implemented mode detection from model + Some code refactoring --- src/slic3r/GUI/GUI_Preview.cpp | 6 +++- src/slic3r/GUI/Plater.cpp | 32 ++++++++++++++++++++ src/slic3r/GUI/Plater.hpp | 1 + src/slic3r/GUI/wxExtensions.cpp | 53 ++++++++++++++++++++++----------- src/slic3r/GUI/wxExtensions.hpp | 33 +++++--------------- 5 files changed, 82 insertions(+), 43 deletions(-) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 1a4d12d316..0c3138c803 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -692,7 +692,11 @@ 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); - m_slider->SetManipulationState(wxGetApp().extruders_edited_cnt()); + + // Detect and set manipulation mode for double slider + m_slider->SetManipulationState( wxGetApp().extruders_edited_cnt() == 1 ? DoubleSlider::msSingleExtruder : + wxGetApp().plater()->is_one_extruder_printed_model() ? DoubleSlider::msMultiAsSingle : + DoubleSlider::msMultiExtruder); } void Preview::reset_double_slider() diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2c07425594..01241bd8f9 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5358,6 +5358,38 @@ 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 4793977058..2c7e13e45a 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -234,6 +234,7 @@ 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 7b36207f52..3f4d43b5b3 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -2861,13 +2861,13 @@ void DoubleSlider::draw_colored_band(wxDC& dc) const wxColour bg_clr = GetParent()->GetBackgroundColour(); - wxColour clr = m_state == msSingleExtruder ? wxColour(colors[0]) : bg_clr; + wxColour clr = m_ticks_.empty() ? bg_clr : wxColour(colors[0]); draw_band(dc, clr, main_band); size_t i = 1; for (auto tick : m_ticks_) { - if ( (m_state == msSingleExtruder && tick.gcode != Slic3r::ColorChangeCode) || + if ( (m_state != msMultiExtruder/*m_state == msSingleExtruder*/ && tick.gcode != Slic3r::ColorChangeCode) || (m_state == msMultiExtruder && tick.gcode != Slic3r::ExtruderChangeCode) ) continue; @@ -3182,31 +3182,50 @@ void DoubleSlider::OnLeftUp(wxMouseEvent& event) if (m_show_context_menu) { - if (m_state == msMultiExtruder) + if (m_state == msSingleExtruder) + add_code(Slic3r::ColorChangeCode); + else { - wxMenu menu; const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt(); if (extruders_cnt > 1) - { - const int initial_extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value); + { + wxMenu menu; + wxMenu* sub_menu = new wxMenu(); + wxString sub_menu_name = _(L("Change extruder")); + std::string menu_icon_name = "change_extruder"; - wxMenu* change_extruder_menu = new wxMenu(); + if (m_state == msMultiAsSingle) + { + int initial_extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value); + if (initial_extruder == 0) + initial_extruder = 1; - for (int i = 0; i <= extruders_cnt; i++) { - const wxString item_name = i == 0 ? _(L("Default")) : wxString::Format(_(L("Extruder %d")), i); + 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(change_extruder_menu, wxID_ANY, item_name, "", - [this, i](wxCommandEvent&) { change_extruder(i); }, &menu)->Check(i == initial_extruder); + 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); + } + + sub_menu_name = from_u8((boost::format(_utf8(L("Add color change (%1%) for:"))) % Slic3r::ColorChangeCode).str()); + menu_icon_name = "colorchange_add_m"; } - wxMenuItem* change_extruder_menu_item = menu.AppendSubMenu(change_extruder_menu, _(L("Change extruder")), _(L("Use another extruder"))); - change_extruder_menu_item->SetBitmap(create_scaled_bitmap(nullptr, "change_extruder")); - } + 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); + } } - else - add_code(Slic3r::ColorChangeCode); m_show_context_menu = false; } diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 390dafab9e..31e60d7d69 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -823,7 +823,10 @@ public: enum ManipulationState { msSingleExtruder, // single extruder printer preset is selected - msMultiExtruder // multiple extruder printer preset is selected, and "Whole print" is selected + msMultiAsSingle, // multiple extruder printer preset is selected, but + // this mode works just for Single extruder print + // (For all print from objects settings is used just one extruder) + msMultiExtruder // multiple extruder printer preset is selected }; void SetManipulationState(ManipulationState state) { m_state = state; @@ -976,31 +979,11 @@ private: public: struct ExtrudersSequence { - bool is_mm_intervals; - double interval_by_mm; - int interval_by_layers; - std::vector extruders; + bool is_mm_intervals = true; + double interval_by_mm = 3.0; + int interval_by_layers = 10; + std::vector extruders = { 0 }; - ExtrudersSequence() : - is_mm_intervals(true), - interval_by_mm(3.0), - interval_by_layers(10), - extruders({ 0 }) {} - - ExtrudersSequence(const ExtrudersSequence& other) : - is_mm_intervals(other.is_mm_intervals), - interval_by_mm(other.interval_by_mm), - interval_by_layers(other.interval_by_layers), - extruders(other.extruders) {} - - ExtrudersSequence& operator=(const ExtrudersSequence& other) { - this->is_mm_intervals = other.is_mm_intervals; - this->interval_by_mm = other.interval_by_mm; - this->interval_by_layers= other.interval_by_layers; - this->extruders = other.extruders; - - return *this; - } bool operator==(const ExtrudersSequence& other) const { return (other.is_mm_intervals == this->is_mm_intervals ) && From aed277089beaaec1a7a5a9936d0ba309f7057b21 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 9 Jan 2020 16:38:59 +0100 Subject: [PATCH 3/8] Updated tooltips and context menus for 3 manipulation mode of DoubleSlider + Some code refactoring --- src/slic3r/GUI/GUI_Preview.cpp | 6 +- src/slic3r/GUI/wxExtensions.cpp | 280 ++++++++++++++++++++++---------- src/slic3r/GUI/wxExtensions.hpp | 50 +++--- 3 files changed, 220 insertions(+), 116 deletions(-) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 0c3138c803..acb5c89e3d 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -694,9 +694,9 @@ void Preview::update_double_slider(const std::vector& layers_z, bool kee m_slider->EnableTickManipulation(color_print_enable); // Detect and set manipulation mode for double slider - m_slider->SetManipulationState( wxGetApp().extruders_edited_cnt() == 1 ? DoubleSlider::msSingleExtruder : - wxGetApp().plater()->is_one_extruder_printed_model() ? DoubleSlider::msMultiAsSingle : - DoubleSlider::msMultiExtruder); + m_slider->SetManipulationMode( wxGetApp().extruders_edited_cnt() == 1 ? DoubleSlider::mmSingleExtruder : + wxGetApp().plater()->is_one_extruder_printed_model() ? DoubleSlider::mmMultiAsSingle : + DoubleSlider::mmMultiExtruder); } void Preview::reset_double_slider() diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 3f4d43b5b3..8ccf605f57 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -2561,7 +2561,7 @@ std::vector DoubleSlider::GetTicksValues() const const int val_size = m_values.size(); if (!m_values.empty()) - for (const TICK_CODE& tick : m_ticks_) { + for (const TICK_CODE& tick : m_ticks) { if (tick.tick > val_size) break; values.emplace_back(t_custom_code{m_values[tick.tick], tick.gcode, tick.extruder, tick.color}); @@ -2575,19 +2575,19 @@ void DoubleSlider::SetTicksValues(const std::vector& heights) if (m_values.empty()) return; - const bool was_empty = m_ticks_.empty(); + const bool was_empty = m_ticks.empty(); - m_ticks_.clear(); + m_ticks.clear(); for (auto h : heights) { auto it = std::lower_bound(m_values.begin(), m_values.end(), h.print_z - epsilon()); if (it == m_values.end()) continue; - m_ticks_.emplace(TICK_CODE{int(it-m_values.begin()), h.gcode, h.extruder, h.color}); + m_ticks.emplace(TICK_CODE{int(it-m_values.begin()), h.gcode, h.extruder, h.color}); } - if (!was_empty && m_ticks_.empty()) + if (!was_empty && m_ticks.empty()) // Switch to the "Feature type"/"Tool" from the very beginning of a new object slicing after deleting of the old one wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED)); @@ -2638,11 +2638,6 @@ void DoubleSlider::render() // draw line draw_scroll_line(dc, lower_pos, higher_pos); -// //lower slider: -// draw_thumb(dc, lower_pos, ssLower); -// //higher slider: -// draw_thumb(dc, higher_pos, ssHigher); - //draw color print ticks draw_ticks(dc); @@ -2668,7 +2663,7 @@ void DoubleSlider::draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoin return; wxBitmap* icon = m_is_action_icon_focesed ? &m_bmp_add_tick_off.bmp() : &m_bmp_add_tick_on.bmp(); - if (m_ticks_.find(TICK_CODE{tick}) != m_ticks_.end()) + if (m_ticks.find(TICK_CODE{tick}) != m_ticks.end()) icon = m_is_action_icon_focesed ? &m_bmp_del_tick_off.bmp() : &m_bmp_del_tick_on.bmp(); wxCoord x_draw, y_draw; @@ -2811,7 +2806,7 @@ void DoubleSlider::draw_ticks(wxDC& dc) int height, width; get_size(&width, &height); const wxCoord mid = is_horizontal() ? 0.5*height : 0.5*width; - for (auto tick : m_ticks_) + for (auto tick : m_ticks) { const wxCoord pos = get_position_from_value(tick.tick); @@ -2834,6 +2829,96 @@ void DoubleSlider::draw_ticks(wxDC& dc) } } +bool DoubleSlider::get_color_for_tick(wxColour& color, std::set::const_iterator tick_it, const std::vector& colors) const +{ + if (m_mode == mmMultiExtruder) + { + color = GetParent()->GetBackgroundColour(); + return true; + } + + const std::string& code = tick_it->gcode; + if ( code == Slic3r::PausePrintCode || + (code != Slic3r::ColorChangeCode && code != Slic3r::ExtruderChangeCode) ) + return false; + + if (m_mode == mmSingleExtruder) { + if (code == Slic3r::ColorChangeCode) { + color = wxColour(tick_it->color); + return true; + } + return false; + } + + const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt(); + const int colors_cnt = colors.size(); + + auto get_m600_color_idx = [extruders_cnt, colors_cnt](const std::set& ticks, std::set::const_iterator it) + { + int shift = 0; + while (it != ticks.begin()) { + --it; + if (it->gcode == Slic3r::ColorChangeCode) + shift++; + } + + if (extruders_cnt + shift >= colors_cnt) + return 0; + return extruders_cnt + shift; + }; + + auto get_color_idx_for_tool_change = [extruders_cnt, colors_cnt, get_m600_color_idx](const std::set& ticks, std::set::const_iterator it) + { + const int current_extruder = it->extruder == 0 ? 1 : it->extruder; + if (extruders_cnt == colors_cnt) // there is no one "M600" + return std::min(extruders_cnt - 1, std::max(current_extruder - 1, 0)); + + auto it_n = it; + while (it_n != ticks.begin()) { + --it_n; + if (it_n->gcode == Slic3r::ColorChangeCode && it_n->extruder == current_extruder) + return get_m600_color_idx(ticks, it_n); + } + + 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) + { + auto it_n = it; + bool is_tool_change = false; + while (it_n != ticks.begin()) { + --it_n; + if (it_n->gcode == Slic3r::ExtruderChangeCode) { + is_tool_change = true; + if (it_n->extruder == it->extruder) + return get_m600_color_idx(ticks, it); + break; + } + } + if (!is_tool_change && it->extruder == 0) // use correct extruder number instead of 0 + return get_m600_color_idx(ticks, it); + + return -1; + }; + + // change tool (extruder) + if (code == Slic3r::ExtruderChangeCode) + color = wxColour(colors[get_color_idx_for_tool_change(m_ticks, tick_it)]); + + // change color for current extruder + if (code == Slic3r::ColorChangeCode) { + const int color_idx = get_color_idx_for_color_change(m_ticks, tick_it); + if (color_idx < 0) + return false; + if (color_idx >= colors_cnt) + return false; + color = wxColour(colors[color_idx]); + } + + return true; +} + void DoubleSlider::draw_colored_band(wxDC& dc) { if (!m_is_enabled_tick_manipulation) @@ -2856,29 +2941,40 @@ void DoubleSlider::draw_colored_band(wxDC& dc) dc.DrawRectangle(band_rc); }; - const std::vector& colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); - int colors_cnt = colors.size(); + const std::vector& colors = Slic3r::GUI::wxGetApp().plater()->get_colors_for_color_print(); const wxColour bg_clr = GetParent()->GetBackgroundColour(); - wxColour clr = m_ticks_.empty() ? bg_clr : wxColour(colors[0]); + wxColour clr = m_ticks.empty() || m_mode == mmMultiExtruder ? bg_clr : wxColour(colors[0]); draw_band(dc, clr, main_band); - size_t i = 1; - for (auto tick : m_ticks_) - { - if ( (m_state != msMultiExtruder/*m_state == msSingleExtruder*/ && tick.gcode != Slic3r::ColorChangeCode) || - (m_state == msMultiExtruder && tick.gcode != Slic3r::ExtruderChangeCode) ) - continue; + if (m_ticks.empty() || m_mode == mmMultiExtruder) + // don't color a band for MultiExtruder mode + return; - const wxCoord pos = get_position_from_value(tick.tick); + std::set::const_iterator tick_it = m_ticks.begin(); + + while (tick_it != m_ticks.end()) + { + if ( (m_mode == mmSingleExtruder && tick_it->gcode != Slic3r::ColorChangeCode ) || + (m_mode == mmMultiAsSingle && !(tick_it->gcode == Slic3r::ExtruderChangeCode || tick_it->gcode == Slic3r::ColorChangeCode)) ) + { + ++tick_it; + continue; + } + + const wxCoord pos = get_position_from_value(tick_it->tick); is_horizontal() ? main_band.SetLeft(SLIDER_MARGIN + pos) : main_band.SetBottom(pos - 1); - clr = (m_state == msMultiExtruder && tick.color.empty()) ? bg_clr : - m_state == msMultiExtruder ? wxColour(colors[std::min(colors_cnt - 1, tick.extruder-1)]) : wxColour(tick.color); + if (!get_color_for_tick(clr, tick_it, colors)) + { + ++tick_it; + continue; + } + draw_band(dc, clr, main_band); - i++; + ++tick_it; } } @@ -2903,7 +2999,7 @@ void DoubleSlider::draw_one_layer_icon(wxDC& dc) void DoubleSlider::draw_revert_icon(wxDC& dc) { - if (m_ticks_.empty() || !m_is_enabled_tick_manipulation) + if (m_ticks.empty() || !m_is_enabled_tick_manipulation) return; int width, height; @@ -2921,7 +3017,7 @@ void DoubleSlider::draw_revert_icon(wxDC& dc) void DoubleSlider::draw_cog_icon(wxDC& dc) { - if (m_state != msMultiExtruder) + if (m_mode != mmMultiExtruder) return; int width, height; @@ -2965,15 +3061,13 @@ void DoubleSlider::detect_selected_slider(const wxPoint& pt) bool DoubleSlider::is_point_in_rect(const wxPoint& pt, const wxRect& rect) { - if (rect.GetLeft() <= pt.x && pt.x <= rect.GetRight() && - rect.GetTop() <= pt.y && pt.y <= rect.GetBottom()) - return true; - return false; + return rect.GetLeft() <= pt.x && pt.x <= rect.GetRight() && + rect.GetTop() <= pt.y && pt.y <= rect.GetBottom(); } int DoubleSlider::is_point_near_tick(const wxPoint& pt) { - for (auto tick : m_ticks_) { + for (auto tick : m_ticks) { const wxCoord pos = get_position_from_value(tick.tick); if (is_horizontal()) { @@ -3034,10 +3128,10 @@ void DoubleSlider::OnLeftDown(wxMouseEvent& event) m_selection == ssLower ? correct_lower_value() : correct_higher_value(); if (!m_selection) m_selection = ssHigher; - m_ticks_.clear(); + m_ticks.clear(); wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED)); } - else if (is_point_in_rect(pos, m_rect_cog_icon) && m_state == msMultiExtruder) { + else if (is_point_in_rect(pos, m_rect_cog_icon) && m_mode == mmMultiExtruder) { // show dialog for set extruder sequence m_edit_extruder_sequence = true; } @@ -3107,17 +3201,18 @@ wxString DoubleSlider::get_tooltip(IconFocus icon_focus) else if (m_is_action_icon_focesed) { const int tick = m_selection == ssLower ? m_lower_value : m_higher_value; - const auto tick_code_it = m_ticks_.find(TICK_CODE{tick}); - tooltip = tick_code_it == m_ticks_.end() ? (m_state == msSingleExtruder ? - _(L("For add color change use left mouse button click")) : - _(L("For add change extruder use left mouse button click"))) + "\n" + - _(L("For add another code use right mouse button click")) : - tick_code_it->gcode == Slic3r::ColorChangeCode ? ( m_state == msSingleExtruder ? + const auto tick_code_it = m_ticks.find(TICK_CODE{tick}); + tooltip = tick_code_it == m_ticks.end() ? (m_mode == mmMultiAsSingle ? + _(L("For add change extruder use left mouse button click")) : + _(L("For add color change use left mouse button click")) ) + "\n" + + _(L("For add another code use right mouse button click")) : + tick_code_it->gcode == Slic3r::ColorChangeCode ? ( m_mode == mmSingleExtruder ? _(L("For Delete color change use left mouse button click\n" "For Edit color use right mouse button click")) : from_u8((boost::format(_utf8(L("Delete color change for Extruder %1%"))) % tick_code_it->extruder).str()) ): -// tick_code_it->gcode == Slic3r::PausePrintCode ? _(L("Delete pause")) : - tick_code_it->gcode == Slic3r::ExtruderChangeCode ? + tick_code_it->gcode == Slic3r::PausePrintCode ? + _(L("Delete pause")) : + tick_code_it->gcode == Slic3r::ExtruderChangeCode ? from_u8((boost::format(_utf8(L("Delete extruder change to \"%1%\""))) % tick_code_it->extruder).str()) : from_u8((boost::format(_utf8(L("For Delete \"%1%\" code use left mouse button click\n" "For Edit \"%1%\" code use right mouse button click"))) % tick_code_it->gcode ).str()); @@ -3138,7 +3233,7 @@ void DoubleSlider::OnMotion(wxMouseEvent& event) if (!m_is_left_down && !m_is_one_layer) { m_is_action_icon_focesed = is_point_in_rect(pos, m_rect_tick_action); - if (!m_ticks_.empty() && is_point_in_rect(pos, m_rect_revert_icon)) + if (!m_ticks.empty() && is_point_in_rect(pos, m_rect_revert_icon)) icon_focus = ifRevert; else if (is_point_in_rect(pos, m_rect_cog_icon)) icon_focus = ifCog; @@ -3182,7 +3277,7 @@ void DoubleSlider::OnLeftUp(wxMouseEvent& event) if (m_show_context_menu) { - if (m_state == msSingleExtruder) + if (m_mode == mmSingleExtruder) add_code(Slic3r::ColorChangeCode); else { @@ -3194,7 +3289,7 @@ void DoubleSlider::OnLeftUp(wxMouseEvent& event) wxString sub_menu_name = _(L("Change extruder")); std::string menu_icon_name = "change_extruder"; - if (m_state == msMultiAsSingle) + if (m_mode == mmMultiAsSingle) { int initial_extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value); if (initial_extruder == 0) @@ -3213,7 +3308,8 @@ void DoubleSlider::OnLeftUp(wxMouseEvent& event) 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, 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()); @@ -3285,13 +3381,13 @@ void DoubleSlider::action_tick(const TicksAction action) const int tick = m_selection == ssLower ? m_lower_value : m_higher_value; - const auto it = m_ticks_.find(TICK_CODE{tick}); + const auto it = m_ticks.find(TICK_CODE{tick}); - if (it != m_ticks_.end()) // erase this tick + if (it != m_ticks.end()) // erase this tick { if (action == taAdd) return; - m_ticks_.erase(TICK_CODE{tick}); + m_ticks.erase(TICK_CODE{tick}); wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED)); Refresh(); @@ -3308,7 +3404,7 @@ void DoubleSlider::action_tick(const TicksAction action) if (m_suppress_add_code) return; m_suppress_add_code = true; - if (m_state != msMultiExtruder) + if (m_mode == mmSingleExtruder) // if (m_mode != mmMultiExtruder) add_code(Slic3r::ColorChangeCode); m_suppress_add_code = false; return; @@ -3395,8 +3491,8 @@ void DoubleSlider::OnRightDown(wxMouseEvent& event) { const int tick = m_selection == ssLower ? m_lower_value : m_higher_value; // if on this Z doesn't exist tick - auto it = m_ticks_.find(TICK_CODE{ tick }); - if (it == m_ticks_.end()) + auto it = m_ticks.find(TICK_CODE{ tick }); + if (it == m_ticks.end()) { // show context menu on OnRightUp() m_show_context_menu = true; @@ -3429,11 +3525,11 @@ void DoubleSlider::OnRightDown(wxMouseEvent& event) int DoubleSlider::get_extruder_for_tick(int tick) { - if (m_ticks_.empty()) + if (m_ticks.empty()) return 0; - auto it = m_ticks_.lower_bound(TICK_CODE{tick}); - while (it != m_ticks_.begin()) { + auto it = m_ticks.lower_bound(TICK_CODE{tick}); + while (it != m_ticks.begin()) { --it; if(it->gcode == Slic3r::ExtruderChangeCode) return it->extruder; @@ -3452,45 +3548,57 @@ void DoubleSlider::OnRightUp(wxMouseEvent& event) if (m_show_context_menu) { wxMenu menu; - if (m_state == msMultiExtruder) + if (m_mode == mmSingleExtruder) + append_menu_item(&menu, wxID_ANY, _(L("Add color change")) + " (M600)", "", + [this](wxCommandEvent&) { add_code(Slic3r::ColorChangeCode); }, "colorchange_add_m", &menu, + [](){return true;}, this); + else { const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt(); if (extruders_cnt > 1) { - const int initial_extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value); + 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 = 0; i <= extruders_cnt; i++) { - const wxString item_name = i == 0 ? _(L("Default")) : wxString::Format(_(L("Extruder %d")), i); + 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); - if (i==0) // don't use M600 for default extruder, if multimaterial print is selected - continue; append_menu_item(add_color_change_menu, wxID_ANY, item_name, "", - [this, i](wxCommandEvent&) { add_code(Slic3r::ColorChangeCode, i); }, "", &menu); + [this, i](wxCommandEvent&) { add_code(Slic3r::ColorChangeCode, i); }, "", &menu, + [](){return true;}, this); } - wxMenuItem* change_extruder_menu_item = menu.AppendSubMenu(change_extruder_menu, _(L("Change extruder")), _(L("Use another 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(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")); } } - else - append_menu_item(&menu, wxID_ANY, _(L("Add color change")) + " (M600)", "", - [this](wxCommandEvent&) { add_code(Slic3r::ColorChangeCode); }, "colorchange_add_m", &menu); append_menu_item(&menu, wxID_ANY, _(L("Add pause print")) + " (M601)", "", - [this](wxCommandEvent&) { add_code(Slic3r::PausePrintCode); }, "pause_print", &menu); + [this](wxCommandEvent&) { add_code(Slic3r::PausePrintCode); }, "pause_print", &menu, + []() {return true; }, this); append_menu_item(&menu, wxID_ANY, _(L("Add custom G-code")), "", - [this](wxCommandEvent&) { add_code(""); }, "edit_gcode", &menu); + [this](wxCommandEvent&) { add_code(""); }, "edit_gcode", &menu, + []() {return true; }, this); Slic3r::GUI::wxGetApp().plater()->PopupMenu(&menu); @@ -3499,7 +3607,7 @@ void DoubleSlider::OnRightUp(wxMouseEvent& event) else if (m_show_edit_menu) { wxMenu menu; - std::set::iterator it = m_ticks_.find(TICK_CODE{ m_selection == ssLower ? m_lower_value : m_higher_value }); + std::set::iterator it = m_ticks.find(TICK_CODE{ m_selection == ssLower ? m_lower_value : m_higher_value }); const bool is_color_change = it->gcode == Slic3r::ColorChangeCode; append_menu_item(&menu, wxID_ANY, it->gcode == Slic3r::ColorChangeCode ? _(L("Edit color")) : @@ -3571,17 +3679,17 @@ void DoubleSlider::add_code(std::string code, int selected_extruder/* = -1*/) { const int tick = m_selection == ssLower ? m_lower_value : m_higher_value; // if on this Z doesn't exist tick - auto it = m_ticks_.find(TICK_CODE{ tick }); - if (it == m_ticks_.end()) + auto it = m_ticks.find(TICK_CODE{ tick }); + if (it == m_ticks.end()) { std::string color = ""; if (code == Slic3r::ColorChangeCode) { std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); - if (m_state == msSingleExtruder && !m_ticks_.empty()) { - auto before_tick_it = std::lower_bound(m_ticks_.begin(), m_ticks_.end(), TICK_CODE{ tick }); - while (before_tick_it != m_ticks_.begin()) { + if (m_mode == mmSingleExtruder && !m_ticks.empty()) { + auto before_tick_it = std::lower_bound(m_ticks.begin(), m_ticks.end(), TICK_CODE{ tick }); + while (before_tick_it != m_ticks.begin()) { --before_tick_it; if (before_tick_it->gcode == Slic3r::ColorChangeCode) { color = before_tick_it->color; @@ -3618,14 +3726,14 @@ void DoubleSlider::add_code(std::string code, int selected_extruder/* = -1*/) } int extruder = 1; - if (m_state == msMultiExtruder) { + if (m_mode != mmSingleExtruder) { if (code == Slic3r::ColorChangeCode && selected_extruder >= 0) extruder = selected_extruder; else extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value); } - m_ticks_.emplace(TICK_CODE{tick, code, extruder, color}); + m_ticks.emplace(TICK_CODE{tick, code, extruder, color}); wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED)); Refresh(); @@ -3637,8 +3745,8 @@ void DoubleSlider::edit_tick() { const int tick = m_selection == ssLower ? m_lower_value : m_higher_value; // if on this Z exists tick - std::set::iterator it = m_ticks_.find(TICK_CODE{ tick }); - if (it != m_ticks_.end()) + std::set::iterator it = m_ticks.find(TICK_CODE{ tick }); + if (it != m_ticks.end()) { std::string edited_value; if (it->gcode == Slic3r::ColorChangeCode) @@ -3663,8 +3771,8 @@ void DoubleSlider::edit_tick() changed_tick.gcode = edited_value; } - m_ticks_.erase(it); - m_ticks_.emplace(changed_tick); + m_ticks.erase(it); + m_ticks.emplace(changed_tick); wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED)); } @@ -3677,9 +3785,9 @@ void DoubleSlider::change_extruder(int extruder) std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); // if on this Y doesn't exist tick - if (m_ticks_.find(TICK_CODE{tick}) == m_ticks_.end()) + if (m_ticks.find(TICK_CODE{tick}) == m_ticks.end()) { - m_ticks_.emplace(TICK_CODE{tick, Slic3r::ExtruderChangeCode, extruder, extruder == 0 ? "" : colors[extruder-1]}); + m_ticks.emplace(TICK_CODE{tick, Slic3r::ExtruderChangeCode, extruder, extruder == 0 ? "" : colors[extruder-1]}); wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED)); Refresh(); @@ -3699,10 +3807,10 @@ void DoubleSlider::edit_extruder_sequence() m_extruders_sequence = from_dlg_val; - auto it = m_ticks_.begin(); - while (it != m_ticks_.end()) { + auto it = m_ticks.begin(); + while (it != m_ticks.end()) { if (it->gcode == Slic3r::ExtruderChangeCode) - it = m_ticks_.erase(it); + it = m_ticks.erase(it); else ++it; } @@ -3717,7 +3825,7 @@ void DoubleSlider::edit_extruder_sequence() while (tick <= m_max_value) { int cur_extruder = m_extruders_sequence.extruders[extruder]; - m_ticks_.emplace(TICK_CODE{tick, Slic3r::ExtruderChangeCode, cur_extruder + 1, colors[cur_extruder]}); + m_ticks.emplace(TICK_CODE{tick, Slic3r::ExtruderChangeCode, cur_extruder + 1, colors[cur_extruder]}); extruder++; if (extruder == extr_cnt) diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 31e60d7d69..87cc922cf7 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -821,20 +821,15 @@ public: EnableTickManipulation(false); } - enum ManipulationState { - msSingleExtruder, // single extruder printer preset is selected - msMultiAsSingle, // multiple extruder printer preset is selected, but + enum ManipulationMode { + mmSingleExtruder, // single extruder printer preset is selected + mmMultiAsSingle, // multiple extruder printer preset is selected, but // this mode works just for Single extruder print // (For all print from objects settings is used just one extruder) - msMultiExtruder // multiple extruder printer preset is selected + mmMultiExtruder // multiple extruder printer preset is selected }; - void SetManipulationState(ManipulationState state) { - m_state = state; - } - void SetManipulationState(int extruders_cnt) { - m_state = extruders_cnt ==1 ? msSingleExtruder : msMultiExtruder; - } - ManipulationState GetManipulationState() const { return m_state; } + void SetManipulationMode(ManipulationMode mode) { m_mode = mode; } + ManipulationMode GetManipulationMode() const { return m_mode; } bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; } bool is_one_layer() const { return m_is_one_layer; } @@ -860,6 +855,17 @@ public: void change_extruder(int extruder); void edit_extruder_sequence(); + struct TICK_CODE + { + bool operator<(const TICK_CODE& other) const { return other.tick > this->tick; } + bool operator>(const TICK_CODE& other) const { return other.tick < this->tick; } + + int tick = 0; + std::string gcode = Slic3r::ColorChangeCode; + int extruder = 0; + std::string color; + }; + protected: void render(); @@ -881,7 +887,6 @@ protected: void detect_selected_slider(const wxPoint& pt); void correct_lower_value(); void correct_higher_value(); - wxString get_tooltip(IconFocus icon_focus); void move_current_thumb(const bool condition); void action_tick(const TicksAction action); void enter_window(wxMouseEvent& event, const bool enter); @@ -897,6 +902,10 @@ protected: wxSize get_size(); void get_size(int *w, int *h); double get_double_value(const SelectedSlider& selection); + wxString get_tooltip(IconFocus icon_focus); + bool get_color_for_tick( wxColour& color, + std::set::const_iterator tick_it, + const std::vector& colors) const; private: bool is_osx { false }; @@ -929,7 +938,7 @@ private: bool m_show_edit_menu = false; bool m_edit_extruder_sequence = false; bool m_suppress_add_code = false; - ManipulationState m_state = msSingleExtruder; + ManipulationMode m_mode = mmSingleExtruder; std::string m_custom_gcode = ""; std::string m_pause_print_msg; @@ -960,21 +969,8 @@ private: std::vector m_line_pens; std::vector m_segm_pens; - std::set m_ticks; std::vector m_values; - - struct TICK_CODE - { - bool operator<(const TICK_CODE& other) const { return other.tick > this->tick; } - bool operator>(const TICK_CODE& other) const { return other.tick < this->tick; } - - int tick = 0; - std::string gcode = Slic3r::ColorChangeCode; - int extruder = 0; - std::string color; - }; - - std::set m_ticks_; + std::set m_ticks; public: struct ExtrudersSequence From 02b2e206281e9cfc89c7efbb4d7d294c1332fe89 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 10 Jan 2020 16:49:07 +0100 Subject: [PATCH 4/8] Context menus improvements. Disabling unused extruders for color_change --- src/slic3r/GUI/GUI_Preview.cpp | 57 +++++++++- src/slic3r/GUI/GUI_Preview.hpp | 3 +- src/slic3r/GUI/Plater.cpp | 32 ------ src/slic3r/GUI/Plater.hpp | 1 - src/slic3r/GUI/wxExtensions.cpp | 190 ++++++++++++++++++-------------- src/slic3r/GUI/wxExtensions.hpp | 18 ++- 6 files changed, 179 insertions(+), 122 deletions(-) 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; From 36de2c5d90df562e0c7b243c942814090b05dd61 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 13 Jan 2020 17:03:10 +0100 Subject: [PATCH 5/8] Code refactoring for context menus and current extruder color selection for tick --- src/slic3r/GUI/wxExtensions.cpp | 196 ++++++++++++-------------------- src/slic3r/GUI/wxExtensions.hpp | 9 +- 2 files changed, 79 insertions(+), 126 deletions(-) diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index a831f32bb6..43af0ab7fa 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -2829,96 +2829,38 @@ void DoubleSlider::draw_ticks(wxDC& dc) } } -bool DoubleSlider::get_color_for_tick(wxColour& color, std::set::const_iterator tick_it, const std::vector& colors) const +std::string DoubleSlider::get_color_for_tool_change_tick(std::set::const_iterator it) const { - if (m_mode == mmMultiExtruder) - { - color = GetParent()->GetBackgroundColour(); - return true; + const int current_extruder = it->extruder == 0 ? std::max(m_only_extruder, 1) : it->extruder; + + auto it_n = it; + while (it_n != m_ticks.begin()) { + --it_n; + if (it_n->gcode == Slic3r::ColorChangeCode && it_n->extruder == current_extruder) + return it_n->color; } - const std::string& code = tick_it->gcode; - if ( code == Slic3r::PausePrintCode || - (code != Slic3r::ColorChangeCode && code != Slic3r::ExtruderChangeCode) ) - return false; + return it->color; +} - if (m_mode == mmSingleExtruder) { - if (code == Slic3r::ColorChangeCode) { - color = wxColour(tick_it->color); - return true; +std::string DoubleSlider::get_color_for_color_change_tick(std::set::const_iterator it) const +{ + const int def_extruder = std::max(1, m_only_extruder); + auto it_n = it; + bool is_tool_change = false; + while (it_n != m_ticks.begin()) { + --it_n; + if (it_n->gcode == Slic3r::ExtruderChangeCode) { + is_tool_change = true; + if (it_n->extruder == it->extruder) + return it->color; + break; } - return false; } + if (!is_tool_change && it->extruder == def_extruder) + return it->color; - const int extruders_cnt = Slic3r::GUI::wxGetApp().extruders_edited_cnt(); - const int colors_cnt = colors.size(); - - auto get_m600_color_idx = [extruders_cnt, colors_cnt](const std::set& ticks, std::set::const_iterator it) - { - int shift = 0; - while (it != ticks.begin()) { - --it; - if (it->gcode == Slic3r::ColorChangeCode) - shift++; - } - - if (extruders_cnt + shift >= colors_cnt) - return 0; - return extruders_cnt + shift; - }; - - auto get_color_idx_for_tool_change = [extruders_cnt, colors_cnt, get_m600_color_idx](const std::set& ticks, std::set::const_iterator it) - { - const int current_extruder = it->extruder == 0 ? 1 : it->extruder; - if (extruders_cnt == colors_cnt) // there is no one "M600" - return std::min(extruders_cnt - 1, std::max(current_extruder - 1, 0)); - - auto it_n = it; - while (it_n != ticks.begin()) { - --it_n; - if (it_n->gcode == Slic3r::ColorChangeCode && it_n->extruder == current_extruder) - return get_m600_color_idx(ticks, it_n); - } - - return std::min(extruders_cnt - 1, std::max(current_extruder - 1, 0)); - }; - - 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; - while (it_n != ticks.begin()) { - --it_n; - if (it_n->gcode == Slic3r::ExtruderChangeCode) { - is_tool_change = true; - if (it_n->extruder == it->extruder) - return get_m600_color_idx(ticks, it); - break; - } - } - if (!is_tool_change && it->extruder == extruder) // use correct extruder number instead of 0 - return get_m600_color_idx(ticks, it); - - return -1; - }; - - // change tool (extruder) - if (code == Slic3r::ExtruderChangeCode) - color = wxColour(colors[get_color_idx_for_tool_change(m_ticks, tick_it)]); - - // change color for current extruder - if (code == Slic3r::ColorChangeCode) { - const int color_idx = get_color_idx_for_color_change(m_ticks, tick_it); - if (color_idx < 0) - return false; - if (color_idx >= colors_cnt) - return false; - color = wxColour(colors[color_idx]); - } - - return true; + return ""; } void DoubleSlider::draw_colored_band(wxDC& dc) @@ -2943,39 +2885,35 @@ void DoubleSlider::draw_colored_band(wxDC& dc) dc.DrawRectangle(band_rc); }; - const std::vector& colors = Slic3r::GUI::wxGetApp().plater()->get_colors_for_color_print(); - - 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); - + // don't color a band for MultiExtruder mode if (m_ticks.empty() || m_mode == mmMultiExtruder) - // don't color a band for MultiExtruder mode + { + draw_band(dc, GetParent()->GetBackgroundColour(), main_band); return; + } + + const int default_color_idx = m_mode==mmMultiAsSingle ? std::max(m_only_extruder - 1, 0) : 0; + draw_band(dc, wxColour(Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config()[default_color_idx]), main_band); std::set::const_iterator tick_it = m_ticks.begin(); while (tick_it != m_ticks.end()) { - if ( (m_mode == mmSingleExtruder && tick_it->gcode != Slic3r::ColorChangeCode ) || - (m_mode == mmMultiAsSingle && !(tick_it->gcode == Slic3r::ExtruderChangeCode || tick_it->gcode == Slic3r::ColorChangeCode)) ) - { - ++tick_it; - continue; + if ( (m_mode == mmSingleExtruder && tick_it->gcode == Slic3r::ColorChangeCode ) || + (m_mode == mmMultiAsSingle && (tick_it->gcode == Slic3r::ExtruderChangeCode || tick_it->gcode == Slic3r::ColorChangeCode)) ) + { + const wxCoord pos = get_position_from_value(tick_it->tick); + is_horizontal() ? main_band.SetLeft(SLIDER_MARGIN + pos) : + main_band.SetBottom(pos - 1); + + const std::string clr_str = m_mode == mmSingleExtruder ? tick_it->color : + tick_it->gcode == Slic3r::ExtruderChangeCode ? + get_color_for_tool_change_tick(tick_it) : + get_color_for_color_change_tick(tick_it); + + if (!clr_str.empty()) + draw_band(dc, wxColour(clr_str), main_band); } - - const wxCoord pos = get_position_from_value(tick_it->tick); - is_horizontal() ? main_band.SetLeft(SLIDER_MARGIN + pos) : - main_band.SetBottom(pos - 1); - - if (!get_color_for_tick(clr, tick_it, colors)) - { - ++tick_it; - continue; - } - - draw_band(dc, clr, main_band); ++tick_it; } } @@ -3281,11 +3219,16 @@ void DoubleSlider::append_change_extruder_menu_item(wxMenu* menu) for (int i = 1; i <= extruders_cnt; i++) { - const wxString item_name = wxString::Format(_(L("Extruder %d")), i); + const bool is_active_extruder = i == initial_extruder; + const wxString item_name = wxString::Format(_(L("Extruder %d")), i) + + (is_active_extruder ? " (" + _(L("active")) + ")" : ""); 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(change_extruder_menu, wxID_ANY, item_name, "", + [this, i](wxCommandEvent&) { change_extruder(i); }, "", menu, + [is_active_extruder]() { return !is_active_extruder; }, Slic3r::GUI::wxGetApp().plater()); +// 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)")); @@ -3313,7 +3256,7 @@ void DoubleSlider::append_add_color_change_menu_item(wxMenu* menu) 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")) + ")"); + (is_used_extruder ? " (" + _(L("used")) + ")" : ""); append_menu_item(add_color_change_menu, wxID_ANY, item_name, "", [this, i](wxCommandEvent&) { add_code(Slic3r::ColorChangeCode, i); }, "", menu, @@ -3575,8 +3518,15 @@ std::set DoubleSlider::get_used_extruders_for_tick(int tick) return {default_initial_extruder}; std::set used_extruders; - - auto it = m_ticks.lower_bound(TICK_CODE{tick}); + auto it_start = m_ticks.lower_bound(TICK_CODE{tick}); + + auto it = it_start; + if (it == m_ticks.begin() && it->gcode == Slic3r::ExtruderChangeCode) { + used_extruders.emplace(it->extruder); + if (tick < it->tick) + used_extruders.emplace(default_initial_extruder); + } + while (it != m_ticks.begin()) { --it; if(it->gcode == Slic3r::ExtruderChangeCode) @@ -3585,10 +3535,11 @@ std::set DoubleSlider::get_used_extruders_for_tick(int tick) break; } } - if (it == m_ticks.begin()) - used_extruders.emplace(default_initial_extruder); - ++it; + if (it == m_ticks.begin() && used_extruders.empty()) + used_extruders.emplace(default_initial_extruder); + + it = it_start; while (it != m_ticks.end()) { if(it->gcode == Slic3r::ExtruderChangeCode) used_extruders.emplace(it->extruder); @@ -3713,21 +3664,22 @@ void DoubleSlider::add_code(std::string code, int selected_extruder/* = -1*/) { std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); - if (m_mode == mmSingleExtruder && !m_ticks.empty()) { + if (m_ticks.empty()) + color = colors[selected_extruder > 0 ? selected_extruder - 1 : std::max(1, m_only_extruder)-1]; + else + { auto before_tick_it = std::lower_bound(m_ticks.begin(), m_ticks.end(), TICK_CODE{ tick }); while (before_tick_it != m_ticks.begin()) { --before_tick_it; - if (before_tick_it->gcode == Slic3r::ColorChangeCode) { + if (before_tick_it->gcode == Slic3r::ColorChangeCode && before_tick_it->extruder == selected_extruder) { color = before_tick_it->color; break; } } if (color.empty()) - color = colors[0]; + color = colors[selected_extruder > 0 ? selected_extruder - 1 : std::max(1, m_only_extruder) - 1]; } - else - color = colors[selected_extruder > 0 ? selected_extruder-1 : 0]; color = get_new_color(color); if (color.empty()) diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 35357cea48..81f4d73423 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -898,6 +898,8 @@ protected: void action_tick(const TicksAction action); void enter_window(wxMouseEvent& event, const bool enter); +private: + bool is_point_in_rect(const wxPoint& pt, const wxRect& rect); int is_point_near_tick(const wxPoint& pt); @@ -910,9 +912,9 @@ protected: void get_size(int *w, int *h); double get_double_value(const SelectedSlider& selection); wxString get_tooltip(IconFocus icon_focus); - bool get_color_for_tick( wxColour& color, - std::set::const_iterator tick_it, - const std::vector& colors) const; + + std::string get_color_for_tool_change_tick(std::set::const_iterator it) const; + std::string get_color_for_color_change_tick(std::set::const_iterator it) const; int get_extruder_for_tick(int tick); std::set get_used_extruders_for_tick(int tick); @@ -920,7 +922,6 @@ protected: void append_change_extruder_menu_item(wxMenu*); void append_add_color_change_menu_item(wxMenu*); -private: bool is_osx { false }; wxFont m_font; int m_min_value; From 15f873dd74824b1a35c44eb4e9333658f300fc79 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 15 Jan 2020 15:35:56 +0100 Subject: [PATCH 6/8] DoubleSlider: Implemented code for check of used extruders for MustiAsSingle mode --- src/libslic3r/GCode/ToolOrdering.cpp | 3 ++- src/libslic3r/Print.hpp | 1 + src/slic3r/GUI/wxExtensions.cpp | 21 ++++++++++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index a76f0fafbf..27abc359a6 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -486,7 +486,8 @@ void ToolOrdering::assign_custom_gcodes(const Print &print) print_z_below = it_lt_below->print_z; if (custom_gcode.print_z > print_z_below + 0.5 * EPSILON) { // The custom G-code applies to the current layer. - if (custom_gcode.gcode != ColorChangeCode || extruder_printing_above[unsigned(custom_gcode.extruder - 1)]) + if ( custom_gcode.gcode != ColorChangeCode || + (custom_gcode.extruder <= num_extruders && extruder_printing_above[unsigned(custom_gcode.extruder - 1)])) // If it is color change, it will actually be useful as the exturder above will print. lt.custom_gcode = &custom_gcode; // Consume that custom G-code event. diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 42f8d761e1..3d1f596d19 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -382,6 +382,7 @@ public: // Accessed by SupportMaterial const PrintRegion* get_region(size_t idx) const { return m_regions[idx]; } + const ToolOrdering& get_tool_ordering() const { return m_wipe_tower_data.tool_ordering; } // #ys_FIXME just for testing protected: // methods for handling regions diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 3872db3fbd..8e1cd0c6f2 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -5,6 +5,7 @@ #include "libslic3r/Utils.hpp" #include "libslic3r/Model.hpp" +#include "libslic3r/Print.hpp" #include #include @@ -3487,7 +3488,25 @@ int DoubleSlider::get_extruder_for_tick(int tick) 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 + { + // #ys_FIXME: get tool ordering from _correct_ place + const Slic3r::ToolOrdering& tool_ordering = Slic3r::GUI::wxGetApp().plater()->fff_print().get_tool_ordering(); + + if (tool_ordering.empty()) + return {}; + + std::set used_extruders; + + auto it_layer_tools = std::lower_bound(tool_ordering.begin(), tool_ordering.end(), Slic3r::LayerTools(m_values[tick])); + for (; it_layer_tools != tool_ordering.end(); it_layer_tools++) + { + const std::vector& extruders = it_layer_tools->extruders; + for (const auto& extruder : extruders) + used_extruders.emplace(extruder+1); + } + + return used_extruders; + } const int default_initial_extruder = m_mode == mmMultiAsSingle ? std::max(m_only_extruder, 1) : 1; if (m_ticks.empty()) From 8ef29aab78ebbf862914eff14b5e111a4b065e9a Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 16 Jan 2020 10:20:36 +0100 Subject: [PATCH 7/8] Refactoring of DoubleSlider::add_code() --- src/slic3r/GUI/wxExtensions.cpp | 96 ++++++++++++++++----------------- 1 file changed, 45 insertions(+), 51 deletions(-) diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 8e1cd0c6f2..f2fed3bf76 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -3652,66 +3652,60 @@ void DoubleSlider::add_code(std::string code, int selected_extruder/* = -1*/) const int tick = m_selection == ssLower ? m_lower_value : m_higher_value; // if on this Z doesn't exist tick auto it = m_ticks.find(TICK_CODE{ tick }); - if (it == m_ticks.end()) + if (it != m_ticks.end()) + return; + + std::string color; + const int extruder = selected_extruder > 0 ? selected_extruder : std::max(1, m_only_extruder); + + if (code == Slic3r::ColorChangeCode) { - std::string color = ""; - if (code == Slic3r::ColorChangeCode) + std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); + + if (m_ticks.empty()) + color = colors[extruder-1]; + else { - std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); - - if (m_ticks.empty()) - color = colors[selected_extruder > 0 ? selected_extruder - 1 : std::max(1, m_only_extruder)-1]; - else - { - auto before_tick_it = std::lower_bound(m_ticks.begin(), m_ticks.end(), TICK_CODE{ tick }); - while (before_tick_it != m_ticks.begin()) { - --before_tick_it; - if (before_tick_it->gcode == Slic3r::ColorChangeCode && before_tick_it->extruder == selected_extruder) { - color = before_tick_it->color; - break; - } + auto before_tick_it = std::lower_bound(m_ticks.begin(), m_ticks.end(), TICK_CODE{ tick }); + while (before_tick_it != m_ticks.begin()) { + --before_tick_it; + if (before_tick_it->gcode == Slic3r::ColorChangeCode && before_tick_it->extruder == extruder) { + color = before_tick_it->color; + break; } - - if (color.empty()) - color = colors[selected_extruder > 0 ? selected_extruder - 1 : std::max(1, m_only_extruder) - 1]; } - color = get_new_color(color); if (color.empty()) - return; - } - else if (code == Slic3r::PausePrintCode) - { - /* PausePrintCode doesn't need a color, so - * this field is used for save a short message shown on Printer display - * */ - color = get_pause_print_msg(m_pause_print_msg, m_values[tick]); - if (color.empty()) - return; - m_pause_print_msg = color; - } - else if (code.empty()) - { - code = get_custom_code(m_custom_gcode, m_values[tick]); - if (code.empty()) - return; - m_custom_gcode = code; + color = colors[extruder-1]; } - int extruder = 1; - if (m_mode != mmSingleExtruder) { - if (code == Slic3r::ColorChangeCode && selected_extruder >= 0) - extruder = selected_extruder; - else - extruder = get_extruder_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value); - } - - m_ticks.emplace(TICK_CODE{tick, code, extruder, color}); - - wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED)); - Refresh(); - Update(); + color = get_new_color(color); + if (color.empty()) + return; } + else if (code == Slic3r::PausePrintCode) + { + /* PausePrintCode doesn't need a color, so + * this field is used for save a short message shown on Printer display + * */ + color = get_pause_print_msg(m_pause_print_msg, m_values[tick]); + if (color.empty()) + return; + m_pause_print_msg = color; + } + else if (code.empty()) + { + code = get_custom_code(m_custom_gcode, m_values[tick]); + if (code.empty()) + return; + m_custom_gcode = code; + } + + m_ticks.emplace(TICK_CODE{tick, code, extruder, color}); + + wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED)); + Refresh(); + Update(); } void DoubleSlider::edit_tick() From 89fcd7f95af4a078f86e5545b31fa9ae0fdd5091 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 16 Jan 2020 16:01:19 +0100 Subject: [PATCH 8/8] Added "mode" variable for custom_gcode_per_print_z --- src/libslic3r/Format/3mf.cpp | 8 ++++---- src/libslic3r/Format/AMF.cpp | 6 +++--- src/libslic3r/GCode/ToolOrdering.cpp | 10 +++++----- src/libslic3r/Model.cpp | 6 +++--- src/libslic3r/Model.hpp | 23 ++++++++++++++++++++++- src/libslic3r/Print.cpp | 2 +- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- src/slic3r/GUI/GUI_Preview.cpp | 8 ++++---- src/slic3r/GUI/Plater.cpp | 6 +++--- src/slic3r/GUI/PresetBundle.cpp | 2 +- 10 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index cca90b4633..ab4848c9a8 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1088,7 +1088,7 @@ namespace Slic3r { return; pt::ptree code_tree = main_tree.front().second; - m_model->custom_gcode_per_print_z.clear(); + m_model->custom_gcode_per_print_z.gcodes.clear(); for (const auto& code : code_tree) { @@ -1100,7 +1100,7 @@ namespace Slic3r { int extruder = tree.get (".extruder" ); std::string color = tree.get (".color" ); - m_model->custom_gcode_per_print_z.push_back(Model::CustomGCode{print_z, gcode, extruder, color}) ; + m_model->custom_gcode_per_print_z.gcodes.push_back(Model::CustomGCode{print_z, gcode, extruder, color}) ; } } } @@ -2631,12 +2631,12 @@ bool _3MF_Exporter::_add_custom_gcode_per_print_z_file_to_archive( mz_zip_archiv { std::string out = ""; - if (!model.custom_gcode_per_print_z.empty()) + if (!model.custom_gcode_per_print_z.gcodes.empty()) { pt::ptree tree; pt::ptree& main_tree = tree.add("custom_gcodes_per_print_z", ""); - for (const Model::CustomGCode& code : model.custom_gcode_per_print_z) + for (const Model::CustomGCode& code : model.custom_gcode_per_print_z.gcodes) { pt::ptree& code_tree = main_tree.add("code", ""); // store minX and maxZ diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 947c044581..efb90f5923 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -653,7 +653,7 @@ void AMFParserContext::endElement(const char * /* name */) int extruder = atoi(m_value[2].c_str()); const std::string& color = m_value[3]; - m_model.custom_gcode_per_print_z.push_back(Model::CustomGCode{height, gcode, extruder, color}); + m_model.custom_gcode_per_print_z.gcodes.push_back(Model::CustomGCode{height, gcode, extruder, color}); for (std::string& val: m_value) val.clear(); @@ -1250,14 +1250,14 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config) stream << " \n"; } - if (!model->custom_gcode_per_print_z.empty()) + if (!model->custom_gcode_per_print_z.gcodes.empty()) { std::string out = ""; pt::ptree tree; pt::ptree& main_tree = tree.add("custom_gcodes_per_height", ""); - for (const Model::CustomGCode& code : model->custom_gcode_per_print_z) + for (const Model::CustomGCode& code : model->custom_gcode_per_print_z.gcodes) { pt::ptree& code_tree = main_tree.add("code", ""); // store minX and maxZ diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 51093c32a0..fe8c93c9a5 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -462,13 +462,13 @@ void ToolOrdering::assign_custom_gcodes(const Print &print) // Only valid for non-sequential print. assert(! print.config().complete_objects.value); - const std::vector &custom_gcode_per_print_z = print.model().custom_gcode_per_print_z; - if (custom_gcode_per_print_z.empty()) + const Model::CustomGCodeInfo &custom_gcode_per_print_z = print.model().custom_gcode_per_print_z; + if (custom_gcode_per_print_z.gcodes.empty()) return; unsigned int num_extruders = *std::max_element(m_all_printing_extruders.begin(), m_all_printing_extruders.end()) + 1; std::vector extruder_printing_above(num_extruders, false); - auto custom_gcode_it = custom_gcode_per_print_z.rbegin(); + auto custom_gcode_it = custom_gcode_per_print_z.gcodes.rbegin(); // If printing on a single extruder machine, make the tool changes trigger color change (M600) events. bool tool_changes_as_color_changes = num_extruders == 1; // From the last layer to the first one: @@ -478,8 +478,8 @@ void ToolOrdering::assign_custom_gcodes(const Print &print) for (unsigned int i : lt.extruders) extruder_printing_above[i] = true; // Skip all custom G-codes above this layer and skip all extruder switches. - for (; custom_gcode_it != custom_gcode_per_print_z.rend() && (custom_gcode_it->print_z > lt.print_z + EPSILON || custom_gcode_it->gcode == ExtruderChangeCode); ++ custom_gcode_it); - if (custom_gcode_it == custom_gcode_per_print_z.rend()) + for (; custom_gcode_it != custom_gcode_per_print_z.gcodes.rend() && (custom_gcode_it->print_z > lt.print_z + EPSILON || custom_gcode_it->gcode == ExtruderChangeCode); ++ custom_gcode_it); + if (custom_gcode_it == custom_gcode_per_print_z.gcodes.rend()) // Custom G-codes were processed. break; // Some custom G-code is configured for this layer or a layer below. diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 812180641b..ead2c95caa 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -126,7 +126,7 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c if (add_default_instances) model.add_default_instances(); - update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config); + update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z.gcodes, config); return model; } @@ -163,7 +163,7 @@ Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig if (add_default_instances) model.add_default_instances(); - update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, config); + update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z.gcodes, config); return model; } @@ -1846,7 +1846,7 @@ arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const std::vector> custom_tool_changes(const Model &model, size_t num_extruders) { std::vector> custom_tool_changes; - for (const Model::CustomGCode &custom_gcode : model.custom_gcode_per_print_z) + for (const Model::CustomGCode &custom_gcode : model.custom_gcode_per_print_z.gcodes) if (custom_gcode.gcode == ExtruderChangeCode) { // If extruder count in PrinterSettings was changed, use default (0) extruder for extruders, more than num_extruders custom_tool_changes.emplace_back(custom_gcode.print_z, static_cast(custom_gcode.extruder > num_extruders ? 1 : custom_gcode.extruder)); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 26bb4cb92f..509c70b15f 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -772,7 +772,28 @@ public: std::string color; // if gcode is equal to PausePrintCode, // this field is used for save a short message shown on Printer display }; - std::vector custom_gcode_per_print_z; + + struct CustomGCodeInfo + { + enum MODE + { + SingleExtruder, // single extruder printer preset is selected + MultiAsSingle, // multiple extruder printer preset is selected, but + // this mode works just for Single extruder print + // (For all print from objects settings is used just one extruder) + MultiExtruder // multiple extruder printer preset is selected + } mode; + + std::vector gcodes; + + bool operator==(const CustomGCodeInfo& rhs) const + { + return (rhs.mode == this->mode ) && + (rhs.gcodes == this->gcodes ); + } + bool operator!=(const CustomGCodeInfo& rhs) const { return !(*this == rhs); } + } + custom_gcode_per_print_z; // Default constructor assigns a new ID to the model. Model() { assert(this->id().valid()); } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index babdd5aa4a..08e43564fa 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -723,7 +723,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ model_object_status.emplace(model_object->id(), ModelObjectStatus::New); } else { if (m_model.custom_gcode_per_print_z != model.custom_gcode_per_print_z) { - update_apply_status(custom_per_printz_gcodes_tool_changes_differ(m_model.custom_gcode_per_print_z, model.custom_gcode_per_print_z) ? + update_apply_status(custom_per_printz_gcodes_tool_changes_differ(m_model.custom_gcode_per_print_z.gcodes, model.custom_gcode_per_print_z.gcodes) ? // The Tool Ordering and the Wipe Tower are no more valid. this->invalidate_steps({ psWipeTower, psGCodeExport }) : // There is no change in Tool Changes stored in custom_gcode_per_print_z, therefore there is no need to update Tool Ordering. diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index d2428cf967..fa34ff9293 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1011,7 +1011,7 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D std::vector& colors, std::vector& cp_legend_items) { - std::vector custom_gcode_per_print_z = wxGetApp().plater()->model().custom_gcode_per_print_z; + std::vector custom_gcode_per_print_z = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes; const int extruders_cnt = wxGetApp().extruders_edited_cnt(); if (extruders_cnt == 1) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index fceaeba3bd..f447127f83 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -564,7 +564,7 @@ void Preview::update_view_type(bool slice_completed) { const DynamicPrintConfig& config = wxGetApp().preset_bundle->project_config; - const wxString& choice = !wxGetApp().plater()->model().custom_gcode_per_print_z.empty() /*&& + const wxString& choice = !wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes.empty() /*&& (wxGetApp().extruders_edited_cnt()==1 || !slice_completed) */? _(L("Color Print")) : config.option("wiping_volumes_matrix")->values.size() > 1 ? @@ -595,7 +595,7 @@ void Preview::create_double_slider() Bind(wxCUSTOMEVT_TICKSCHANGED, [this](wxEvent&) { Model& model = wxGetApp().plater()->model(); - model.custom_gcode_per_print_z = m_slider->GetTicksValues(); + model.custom_gcode_per_print_z.gcodes = m_slider->GetTicksValues(); m_schedule_background_process(); update_view_type(false); @@ -664,7 +664,7 @@ void Preview::update_double_slider(const std::vector& layers_z, bool kee bool snap_to_min = force_sliders_full_range || m_slider->is_lower_at_min(); bool snap_to_max = force_sliders_full_range || m_slider->is_higher_at_max(); - std::vector &ticks_from_model = wxGetApp().plater()->model().custom_gcode_per_print_z; + std::vector &ticks_from_model = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes; check_slider_values(ticks_from_model, layers_z); m_slider->SetSliderValues(layers_z); @@ -837,7 +837,7 @@ void Preview::load_print_as_fff(bool keep_z_range) colors.push_back("#808080"); // gray color for pause print or custom G-code if (!gcode_preview_data_valid) - color_print_values = wxGetApp().plater()->model().custom_gcode_per_print_z; + color_print_values = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes; } else if (gcode_preview_data_valid || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool) ) { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index dc720ddaee..6f77c1db64 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2791,7 +2791,7 @@ void Plater::priv::reset() // The hiding of the slicing results, if shown, is not taken care by the background process, so we do it here this->sidebar->show_sliced_info_sizer(false); - model.custom_gcode_per_print_z.clear(); + model.custom_gcode_per_print_z.gcodes.clear(); } void Plater::priv::mirror(Axis axis) @@ -5349,9 +5349,9 @@ std::vector Plater::get_extruder_colors_from_plater_config() const std::vector Plater::get_colors_for_color_print() const { std::vector colors = get_extruder_colors_from_plater_config(); - colors.reserve(colors.size() + p->model.custom_gcode_per_print_z.size()); + colors.reserve(colors.size() + p->model.custom_gcode_per_print_z.gcodes.size()); - for (const Model::CustomGCode& code : p->model.custom_gcode_per_print_z) + for (const Model::CustomGCode& code : p->model.custom_gcode_per_print_z.gcodes) if (code.gcode == ColorChangeCode) colors.emplace_back(code.color); diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 219d7b89da..8f5d58bc13 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -877,7 +877,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool // 4) Load the project config values (the per extruder wipe matrix etc). this->project_config.apply_only(config, s_project_options); - update_custom_gcode_per_print_z_from_config(GUI::wxGetApp().plater()->model().custom_gcode_per_print_z, &this->project_config); + update_custom_gcode_per_print_z_from_config(GUI::wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes, &this->project_config); break; }