diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp index f1f2b5e31d..0823a58977 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSlider.cpp @@ -17,16 +17,9 @@ #include "Tab.hpp" #include "GUI_ObjectList.hpp" -#include #include -#include -#include #include -#include -#include -#include #include -#include #include #include @@ -60,8 +53,6 @@ bool equivalent_areas(const double& bottom_area, const double& top_area) return fabs(bottom_area - top_area) <= miscalculation; } -wxDEFINE_EVENT(wxCUSTOMEVT_TICKSCHANGED, wxEvent); - static std::string gcode(Type type) { const PrintConfig& config = GUI::wxGetApp().plater()->fff_print().config(); @@ -73,88 +64,7 @@ static std::string gcode(Type type) } } -Control::Control( wxWindow *parent, - int lowerValue, - int higherValue, - int minValue, - int maxValue, - long style, - const wxString& name) : - wxControl(parent, wxID_ANY, wxDefaultPosition, wxSize(0,0)), - m_allow_editing(wxGetApp().is_editor()), - m_show_estimated_times(style == wxSL_VERTICAL) -{ -#ifdef __WXOSX__ - is_osx = true; -#endif //__WXOSX__ - - m_ticks.set_pause_print_msg(_u8L("Place bearings in slots and resume printing")); - m_ticks.set_extruder_colors(&m_extruder_colors); - - imgui_ctrl = ImGuiControl( lowerValue, higherValue, - minValue, maxValue, - ImVec2(0.f, 0.f), ImVec2(0.f, 0.f), - style == wxSL_VERTICAL ? ImGuiSliderFlags_Vertical : 0, - into_u8(name), style == wxSL_VERTICAL); - - imgui_ctrl.set_get_label_cb([this](int pos) {return into_u8(get_label(pos)); }); - - if (!imgui_ctrl.is_horizontal()) { - imgui_ctrl.set_get_label_on_move_cb([this](int pos) { return m_show_estimated_times ? into_u8(get_label(pos, ltEstimatedTime)) : ""; }); - imgui_ctrl.set_extra_draw_cb([this](const ImRect& draw_rc) {return draw_ticks(draw_rc); }); - } - -} - -void Control::SetLowerValue(const int lower_val) -{ - imgui_ctrl.SetLowerValue(lower_val); - - wxCommandEvent e(wxEVT_SCROLL_CHANGED); - e.SetEventObject(this); - ProcessWindowEvent(e); -} - -void Control::SetHigherValue(const int higher_val) -{ - imgui_ctrl.SetHigherValue(higher_val); - - wxCommandEvent e(wxEVT_SCROLL_CHANGED); - e.SetEventObject(this); - ProcessWindowEvent(e); -} - -void Control::SetSelectionSpan(const int lower_val, const int higher_val) -{ - imgui_ctrl.SetSelectionSpan(lower_val, higher_val); - - wxCommandEvent e(wxEVT_SCROLL_CHANGED); - e.SetEventObject(this); - ProcessWindowEvent(e); -} - -void Control::SetMaxValue(const int max_value) -{ - imgui_ctrl.SetMaxValue(max_value); -} - -void Control::SetSliderValues(const std::vector& values) -{ - m_values = values; -} - -double Control::get_double_value(const SelectedSlider& selection) -{ - if (m_values.empty() || imgui_ctrl.GetLowerValue() < 0) - return 0.0; - if (m_values.size() <= size_t(imgui_ctrl.GetHigherValue())) { - imgui_ctrl.correct_higher_value(); - return m_values.back(); - } - return m_values[selection == ssLower ? imgui_ctrl.GetLowerValue() : imgui_ctrl.GetHigherValue()]; -} - -int Control::get_tick_from_value(double value, bool force_lower_bound/* = false*/) +int DSManagerForLayers::get_tick_from_value(double value, bool force_lower_bound/* = false*/) { std::vector::iterator it; if (m_is_wipe_tower && !force_lower_bound) @@ -168,7 +78,7 @@ int Control::get_tick_from_value(double value, bool force_lower_bound/* = false* return int(it - m_values.begin()); } -Info Control::GetTicksValues() const +Info DSManagerForLayers::GetTicksValues() const { Info custom_gcode_per_print_z; std::vector& values = custom_gcode_per_print_z.gcodes; @@ -187,7 +97,7 @@ Info Control::GetTicksValues() const return custom_gcode_per_print_z; } -void Control::SetTicksValues(const Info& custom_gcode_per_print_z) +void DSManagerForLayers::SetTicksValues(const Info& custom_gcode_per_print_z) { if (m_values.empty()) { m_ticks.mode = m_mode; @@ -217,7 +127,7 @@ void Control::SetTicksValues(const Info& custom_gcode_per_print_z) m_ticks.mode = custom_gcode_per_print_z.mode; } -void Control::SetLayersTimes(const std::vector& layers_times, float total_time) +void DSManagerForLayers::SetLayersTimes(const std::vector& layers_times, float total_time) { m_layers_times.clear(); if (layers_times.empty()) @@ -243,7 +153,7 @@ void Control::SetLayersTimes(const std::vector& layers_times, float total } } -void Control::SetLayersTimes(const std::vector& layers_times) +void DSManagerForLayers::SetLayersTimes(const std::vector& layers_times) { m_is_wipe_tower = false; m_layers_times = layers_times; @@ -251,15 +161,16 @@ void Control::SetLayersTimes(const std::vector& layers_times) m_layers_times[i] += m_layers_times[i - 1]; } -void Control::SetDrawMode(bool is_sla_print, bool is_sequential_print) +void DSManagerForLayers::SetDrawMode(bool is_sla_print, bool is_sequential_print) { m_draw_mode = is_sla_print ? dmSlaPrint : is_sequential_print ? dmSequentialFffPrint : - dmRegular; + dmRegular; + update_callbacks(); } -void Control::SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder) +void DSManagerForLayers::SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder) { m_mode = !is_one_extruder_printed_model ? MultiExtruder : only_extruder < 0 ? SingleExtruder : @@ -274,28 +185,21 @@ void Control::SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, c m_is_wipe_tower = m_mode != SingleExtruder; } -void Control::SetExtruderColors( const std::vector& extruder_colors) +void DSManagerForLayers::SetExtruderColors( const std::vector& extruder_colors) { m_extruder_colors = extruder_colors; } -bool Control::IsNewPrint() +bool DSManagerForLayers::IsNewPrint(const std::string& idxs) { - if (GUI::wxGetApp().plater()->printer_technology() == ptSLA) - return false; - const Print& print = GUI::wxGetApp().plater()->fff_print(); - std::string idxs; - for (auto object : print.objects()) - idxs += std::to_string(object->id().id) + "_"; - - if (idxs == m_print_obj_idxs) + if (idxs == "sla" || idxs == m_print_obj_idxs) return false; m_print_obj_idxs = idxs; return true; } -void Control::update_callbacks() +void DSManagerForLayers::update_callbacks() { if (m_ticks.empty() || m_draw_mode == dmSequentialFffPrint) imgui_ctrl.set_draw_scroll_line_cb(nullptr); @@ -305,7 +209,7 @@ void Control::update_callbacks() using namespace ImGui; -void Control::draw_ticks(const ImRect& slideable_region) +void DSManagerForLayers::draw_ticks(const ImRect& slideable_region) { //if(m_draw_mode != dmRegular) // return; @@ -414,7 +318,7 @@ static std::array decode_color_to_float_array(const std::string color) return ret; } -void Control::draw_colored_band(const ImRect& groove, const ImRect& slideable_region) +void DSManagerForLayers::draw_colored_band(const ImRect& groove, const ImRect& slideable_region) { if (m_ticks.empty() || m_draw_mode == dmSequentialFffPrint) return; @@ -476,7 +380,7 @@ void Control::draw_colored_band(const ImRect& groove, const ImRect& slideable_re } } -void Control::render_menu() +void DSManagerForLayers::render_menu() { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 10.0f) * m_scale); ImGui::PushStyleVar(ImGuiStyleVar_PopupRounding, 4.0f * m_scale); @@ -538,7 +442,7 @@ void Control::render_menu() ImGui::PopStyleVar(3); } -bool Control::render_button(const wchar_t btn_icon, const wchar_t btn_icon_hovered, const std::string& label_id, const ImVec2& pos, FocusedItem focus, int tick /*= -1*/) +bool DSManagerForLayers::render_button(const wchar_t btn_icon, const wchar_t btn_icon_hovered, const std::string& label_id, const ImVec2& pos, FocusedItem focus, int tick /*= -1*/) { float scale = (float)wxGetApp().em_unit() / 10.0f; @@ -576,85 +480,76 @@ bool Control::render_button(const wchar_t btn_icon, const wchar_t btn_icon_hover return ret; } -void Control::imgui_render(GUI::GLCanvas3D& canvas, float extra_scale/* = 0.1f*/) +void DSManagerForGcode::imgui_render(const int canvas_width, const int canvas_height, float extra_scale/* = 0.1f*/) { if (!imgui_ctrl.IsShown()) return; m_scale = extra_scale * 0.1f * wxGetApp().em_unit(); - const Size cnv_size = canvas.get_canvas_size(); - const int canvas_width = cnv_size.get_width(); - const int canvas_height = cnv_size.get_height(); + ImVec2 pos = ImVec2{std::max(LEFT_MARGIN, 0.2f * canvas_width), canvas_height - HORIZONTAL_SLIDER_WIDTH * m_scale}; + ImVec2 size = ImVec2(canvas_width - 2 * pos.x, HORIZONTAL_SLIDER_WIDTH * m_scale); + + imgui_ctrl.Init(pos, size, m_scale); + if (imgui_ctrl.render()) + process_thumb_move(); +} + +void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_height, float extra_scale/* = 0.1f*/) +{ + if (!imgui_ctrl.IsShown()) + return; + m_scale = extra_scale * 0.1f * wxGetApp().em_unit(); + + const float action_btn_sz = wxGetApp().imgui()->GetTextureCustomRect(ImGui::DSRevert)->Height; + const float tick_icon_side = wxGetApp().imgui()->GetTextureCustomRect(ImGui::PausePrint)->Height; ImVec2 pos; ImVec2 size; - const float action_btn_sz = wxGetApp().imgui()->GetTextureCustomRect(ImGui::DSRevert)->Height; - - if (imgui_ctrl.is_horizontal()) { - pos.x = std::max(LEFT_MARGIN, 0.2f * canvas_width); - pos.y = canvas_height - HORIZONTAL_SLIDER_WIDTH * m_scale; - size = ImVec2(canvas_width - 2 * pos.x, HORIZONTAL_SLIDER_WIDTH * m_scale); - imgui_ctrl.ShowLabelOnMouseMove(false); - } - else { - const float tick_icon_side = wxGetApp().imgui()->GetTextureCustomRect(ImGui::PausePrint)->Height; - - pos.x = canvas_width - VERTICAL_SLIDER_HEIGHT * m_scale - tick_icon_side; - pos.y = 1.f * action_btn_sz; - if (m_allow_editing) - pos.y += 2.f; - size = ImVec2(VERTICAL_SLIDER_HEIGHT * m_scale, canvas_height - 4.f * action_btn_sz); - imgui_ctrl.ShowLabelOnMouseMove(true); - } + pos.x = canvas_width - VERTICAL_SLIDER_HEIGHT * m_scale - tick_icon_side; + pos.y = 1.f * action_btn_sz; + if (m_allow_editing) + pos.y += 2.f; + size = ImVec2(VERTICAL_SLIDER_HEIGHT * m_scale, canvas_height - 4.f * action_btn_sz); + imgui_ctrl.ShowLabelOnMouseMove(true); imgui_ctrl.Init(pos, size, m_scale); - if (imgui_ctrl.render()) { - wxCommandEvent e(wxEVT_SCROLL_CHANGED); - e.SetEventObject(this); - ProcessWindowEvent(e); - } - if (imgui_ctrl.render()) { // request one more frame if value was changes with mouse wheel if (GImGui->IO.MouseWheel != 0.0f) wxGetApp().imgui()->set_requires_extra_frame(); - - wxCommandEvent e(wxEVT_SCROLL_CHANGED); - e.SetEventObject(this); - ProcessWindowEvent(e); + process_thumb_move(); } // draw action buttons - if (!imgui_ctrl.is_horizontal()) { - const float groove_center_x = imgui_ctrl.GetGrooveRect().GetCenter().x; - - ImVec2 btn_pos = ImVec2(groove_center_x - 0.5f * action_btn_sz, pos.y - 0.25f * action_btn_sz); - if (!m_ticks.empty() && m_allow_editing && - render_button(ImGui::DSRevert, ImGui::DSRevertHovered, "revert", btn_pos, fiRevertIcon)) - discard_all_thicks(); + const float groove_center_x = imgui_ctrl.GetGrooveRect().GetCenter().x; - btn_pos.y += 0.1f * action_btn_sz + size.y; - const bool is_one_layer = imgui_ctrl.IsCombineThumbs(); - if (render_button(is_one_layer ? ImGui::Lock : ImGui::Unlock, is_one_layer ? ImGui::LockHovered : ImGui::UnlockHovered, "one_layer", btn_pos, fiOneLayerIcon)) - imgui_ctrl.CombineThumbs(!is_one_layer); + ImVec2 btn_pos = ImVec2(groove_center_x - 0.5f * action_btn_sz, pos.y - 0.25f * action_btn_sz); - btn_pos.y += 1.2f * action_btn_sz; - if (render_button(ImGui::DSSettings, ImGui::DSSettingsHovered, "settings", btn_pos, fiCogIcon)) - show_cog_icon_context_menu(); + if (!m_ticks.empty() && m_allow_editing && + render_button(ImGui::DSRevert, ImGui::DSRevertHovered, "revert", btn_pos, fiRevertIcon)) + discard_all_thicks(); - if (m_draw_mode == dmSequentialFffPrint && imgui_ctrl.is_rclick_on_thumb()) { - std::string tooltip = _u8L("The sequential print is on.\n" - "It's impossible to apply any custom G-code for objects printing sequentually."); - ImGuiPureWrap::tooltip(tooltip, ImGui::GetFontSize() * 20.0f); - } - else if (m_allow_editing) - render_menu(); + btn_pos.y += 0.1f * action_btn_sz + size.y; + const bool is_one_layer = imgui_ctrl.IsCombineThumbs(); + if (render_button(is_one_layer ? ImGui::Lock : ImGui::Unlock, is_one_layer ? ImGui::LockHovered : ImGui::UnlockHovered, "one_layer", btn_pos, fiOneLayerIcon)) + ChangeOneLayerLock(); + + btn_pos.y += 1.2f * action_btn_sz; + if (render_button(ImGui::DSSettings, ImGui::DSSettingsHovered, "settings", btn_pos, fiCogIcon)) + show_cog_icon_context_menu(); + + if (m_draw_mode == dmSequentialFffPrint && imgui_ctrl.is_rclick_on_thumb()) { + std::string tooltip = _u8L("The sequential print is on.\n" + "It's impossible to apply any custom G-code for objects printing sequentually."); + ImGuiPureWrap::tooltip(tooltip, ImGui::GetFontSize() * 20.0f); } + else if (m_allow_editing) + render_menu(); } -bool Control::is_wipe_tower_layer(int tick) const +bool DSManagerForLayers::is_wipe_tower_layer(int tick) const { if (!m_is_wipe_tower || tick >= (int)m_values.size()) return false; @@ -667,7 +562,7 @@ bool Control::is_wipe_tower_layer(int tick) const return false; } -static wxString short_and_splitted_time(const std::string& time) +static std::string short_and_splitted_time(const std::string& time) { // Parse the dhms time format. int days = 0; @@ -690,30 +585,30 @@ static wxString short_and_splitted_time(const std::string& time) auto get_s = [seconds](){ return GUI::format(_u8L("%1%s"), seconds); }; if (days > 0) - return format_wxstr("%1%%2%\n%3%", get_d(), get_h(), get_m()); + return GUI::format("%1%%2%\n%3%", get_d(), get_h(), get_m()); if (hours > 0) { if (hours < 10 && minutes < 10 && seconds < 10) - return format_wxstr("%1%%2%%3%", get_h(), get_m(), get_s()); + return GUI::format("%1%%2%%3%", get_h(), get_m(), get_s()); if (hours > 10 && minutes > 10 && seconds > 10) - return format_wxstr("%1%\n%2%\n%3%", get_h(), get_m(), get_s()); + return GUI::format("%1%\n%2%\n%3%", get_h(), get_m(), get_s()); if ((minutes < 10 && seconds > 10) || (minutes > 10 && seconds < 10)) - return format_wxstr("%1%\n%2%%3%", get_h(), get_m(), get_s()); - return format_wxstr("%1%%2%\n%3%", get_h(), get_m(), get_s()); + return GUI::format("%1%\n%2%%3%", get_h(), get_m(), get_s()); + return GUI::format("%1%%2%\n%3%", get_h(), get_m(), get_s()); } if (minutes > 0) { if (minutes > 10 && seconds > 10) - return format_wxstr("%1%\n%2%", get_m(), get_s()); - return format_wxstr("%1%%2%", get_m(), get_s()); + return GUI::format("%1%\n%2%", get_m(), get_s()); + return GUI::format("%1%%2%", get_m(), get_s()); } - return from_u8(get_s()); + return get_s(); } -wxString Control::get_label(int tick, LabelType label_type/* = ltHeightWithLayer*/) const +std::string DSManagerForLayers::get_label(int pos, LabelType label_type/* = ltHeightWithLayer*/) const { - const size_t value = tick; + const size_t value = pos; if (m_values.empty()) - return wxString::Format("%lu", static_cast(value)); + return GUI::format("%1%", pos); if (value >= m_values.size()) return "ErrVal"; @@ -738,29 +633,25 @@ wxString Control::get_label(int tick, LabelType label_type/* = ltHeightWithLayer return size_t(it - m_layers_values.begin()); }; - if (m_draw_mode == dmSequentialGCodeView) - return wxString::Format("%lu", static_cast(m_alternate_values[value])); - else { - if (label_type == ltEstimatedTime) { - if (m_is_wipe_tower) { - size_t layer_number = get_layer_number(value, label_type); - return (layer_number == size_t(-1) || layer_number == m_layers_times.size()) ? "" : short_and_splitted_time(get_time_dhms(m_layers_times[layer_number])); - } - return value < m_layers_times.size() ? short_and_splitted_time(get_time_dhms(m_layers_times[value])) : ""; - } - wxString str = wxString::Format("%.*f", 2, m_values[value]); - if (label_type == ltHeight) - return str; - if (label_type == ltHeightWithLayer) { - size_t layer_number = m_is_wipe_tower ? get_layer_number(value, label_type) + 1 : (m_values.empty() ? value : value + 1); - return format_wxstr("%1%\n(%2%)", str, layer_number); + if (label_type == ltEstimatedTime) { + if (m_is_wipe_tower) { + size_t layer_number = get_layer_number(value, label_type); + return (layer_number == size_t(-1) || layer_number == m_layers_times.size()) ? "" : short_and_splitted_time(get_time_dhms(m_layers_times[layer_number])); } + return value < m_layers_times.size() ? short_and_splitted_time(get_time_dhms(m_layers_times[value])) : ""; } + std::string str = GUI::format("%1$.2f", m_values[value]); + if (label_type == ltHeight) + return str; + if (label_type == ltHeightWithLayer) { + size_t layer_number = m_is_wipe_tower ? get_layer_number(value, label_type) + 1 : (m_values.empty() ? value : value + 1); + return GUI::format("%1%\n(%2%)", str, layer_number); + } - return wxEmptyString; + return ""; } -std::string Control::get_color_for_tool_change_tick(std::set::const_iterator it) const +std::string DSManagerForLayers::get_color_for_tool_change_tick(std::set::const_iterator it) const { const int current_extruder = it->extruder == 0 ? std::max(m_only_extruder, 1) : it->extruder; @@ -774,7 +665,7 @@ std::string Control::get_color_for_tool_change_tick(std::set::const_it return m_extruder_colors[current_extruder-1]; // return a color for a specific extruder from the colors list } -std::string Control::get_color_for_color_change_tick(std::set::const_iterator it) const +std::string DSManagerForLayers::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; @@ -796,23 +687,13 @@ std::string Control::get_color_for_color_change_tick(std::set::const_i return ""; } -bool Control::is_lower_thumb_editable() +void DSManagerForLayers::ChangeOneLayerLock() { - if (m_draw_mode == dmSequentialGCodeView) - return Slic3r::GUI::get_app_config()->get("seq_top_layer_only") == "0"; - return true; + imgui_ctrl.CombineThumbs(!imgui_ctrl.IsCombineThumbs()); + process_thumb_move(); } -void Control::ChangeOneLayerLock() -{ - imgui_ctrl.CombineThumbs(imgui_ctrl.IsCombineThumbs()); - - wxCommandEvent e(wxEVT_SCROLL_CHANGED); - e.SetEventObject(this); - ProcessWindowEvent(e); -} - -wxString Control::get_tooltip(int tick/*=-1*/) +wxString DSManagerForLayers::get_tooltip(int tick/*=-1*/) { if (m_focus == fiNone) return ""; @@ -822,15 +703,12 @@ wxString Control::get_tooltip(int tick/*=-1*/) return _L("Discard all custom changes"); if (m_focus == fiCogIcon) { - if (m_draw_mode == dmSequentialGCodeView) - return _L("Jump to move") + " (Shift + G)"; - else - return m_mode == MultiAsSingle ? - GUI::from_u8((boost::format(_u8L("Jump to height %s\n" - "Set ruler mode\n" - "or Set extruder sequence for the entire print")) % "(Shift + G)").str()) : - GUI::from_u8((boost::format(_u8L("Jump to height %s\n" - "or Set ruler mode")) % "(Shift + G)").str()); + return m_mode == MultiAsSingle ? + GUI::from_u8((boost::format(_u8L("Jump to height %s\n" + "Set ruler mode\n" + "or Set extruder sequence for the entire print")) % "(Shift + G)").str()) : + GUI::from_u8((boost::format(_u8L("Jump to height %s\n" + "or Set ruler mode")) % "(Shift + G)").str()); } if (m_focus == fiColorBand) return m_mode != SingleExtruder ? "" : @@ -943,7 +821,7 @@ wxString Control::get_tooltip(int tick/*=-1*/) } -void Control::append_change_extruder_menu_item(wxMenu* menu, bool switch_current_code/* = false*/) +void DSManagerForLayers::append_change_extruder_menu_item(wxMenu* menu, bool switch_current_code/* = false*/) { const int extruders_cnt = GUI::wxGetApp().extruders_edited_cnt(); if (extruders_cnt > 1) { @@ -974,7 +852,7 @@ void Control::append_change_extruder_menu_item(wxMenu* menu, bool switch_current } } -void Control::append_add_color_change_menu_item(wxMenu* menu, bool switch_current_code/* = false*/) +void DSManagerForLayers::append_add_color_change_menu_item(wxMenu* menu, bool switch_current_code/* = false*/) { const int extruders_cnt = GUI::wxGetApp().extruders_edited_cnt(); if (extruders_cnt > 1) { @@ -1002,86 +880,16 @@ void Control::append_add_color_change_menu_item(wxMenu* menu, bool switch_curren } } -// "condition" have to be true for: -// - value increase (if wxSL_VERTICAL) -// - value decrease (if wxSL_HORIZONTAL) -void Control::move_current_thumb(const bool condition) -{ -// m_is_one_layer = wxGetKeyState(WXK_CONTROL); - int delta = condition ? -1 : 1; - if (imgui_ctrl.is_horizontal()) - delta *= -1; - - // accelerators - int accelerator = 0; - if (wxGetKeyState(WXK_SHIFT)) - accelerator += 5; - if (wxGetKeyState(WXK_CONTROL)) - accelerator += 5; - if (accelerator > 0) - delta *= accelerator; - - imgui_ctrl.MoveActiveThumb(delta); - - wxCommandEvent e(wxEVT_SCROLL_CHANGED); - e.SetEventObject(this); - ProcessWindowEvent(e); -} - -void Control::UseDefaultColors(bool def_colors_on) +void DSManagerForLayers::UseDefaultColors(bool def_colors_on) { m_ticks.set_default_colors(def_colors_on); } -void Control::OnKeyDown(wxKeyEvent &event) -{ - const int key = event.GetKeyCode(); - if (m_draw_mode != dmSequentialGCodeView && key == WXK_NUMPAD_ADD) { - // OnChar() is called immediately after OnKeyDown(), which can cause call of add_tick() twice. - // To avoid this case we should suppress second add_tick() call. - m_ticks.suppress_plus(true); - add_current_tick(true); - } - else if (m_draw_mode != dmSequentialGCodeView && (key == WXK_NUMPAD_SUBTRACT || key == WXK_DELETE || key == WXK_BACK)) { - // OnChar() is called immediately after OnKeyDown(), which can cause call of delete_tick() twice. - // To avoid this case we should suppress second delete_tick() call. - m_ticks.suppress_minus(true); - delete_current_tick(); - } - else if (m_draw_mode != dmSequentialGCodeView && event.GetKeyCode() == WXK_SHIFT) - UseDefaultColors(false); - else if (imgui_ctrl.is_horizontal()) { - if (key == WXK_LEFT || key == WXK_RIGHT) - move_current_thumb(key == WXK_LEFT); - } - else if (key == WXK_UP || key == WXK_DOWN) - move_current_thumb(key == WXK_UP); - - event.Skip(); // !Needed to have EVT_CHAR generated as well -} - -void Control::OnChar(wxKeyEvent& event) -{ - const int key = event.GetKeyCode(); - if (m_draw_mode != dmSequentialGCodeView) { - if (key == '+' && !m_ticks.suppressed_plus()) { - add_current_tick(true); - m_ticks.suppress_plus(false); - } - else if (key == '-' && !m_ticks.suppressed_minus()) { - delete_current_tick(); - m_ticks.suppress_minus(false); - } - } - if (key == 'G') - jump_to_value(); -} - // Get active extruders for tick. // Means one current extruder for not existing tick OR // 2 extruders - for existing tick (extruder before ToolChange and extruder of current existing tick) // Use those values to disable selection of active extruders -std::array Control::get_active_extruders_for_tick(int tick) const +std::array DSManagerForLayers::get_active_extruders_for_tick(int tick) const { int default_initial_extruder = m_mode == MultiAsSingle ? std::max(1, m_only_extruder) : 1; std::array extruders = { default_initial_extruder, -1 }; @@ -1164,7 +972,7 @@ std::set TickCodeInfo::get_used_extruders_for_tick(int tick, int only_extru return used_extruders; } -void Control::show_cog_icon_context_menu() +void DSManagerForLayers::show_cog_icon_context_menu() { wxMenu menu; @@ -1217,12 +1025,12 @@ bool check_color_change(const PrintObject* object, size_t frst_layer_id, size_t return detected; } -void Control::auto_color_change() +void DSManagerForLayers::auto_color_change() { if (!m_ticks.empty()) { wxString msg_text = _L("This action will cause deletion of all ticks on vertical slider.") + "\n\n" + _L("This action is not revertible.\nDo you want to proceed?"); - GUI::WarningDialog dialog(m_parent, msg_text, _L("Warning"), wxYES | wxNO); + GUI::WarningDialog dialog(nullptr, msg_text, _L("Warning"), wxYES | wxNO); if (dialog.ShowModal() == wxID_NO) return; m_ticks.ticks.clear(); @@ -1364,9 +1172,9 @@ static std::string get_pause_print_msg(const std::string& msg_in, double height) static double get_value_to_jump(double active_value, double min_z, double max_z, DrawMode mode) { - wxString msg_text = (mode == dmSequentialGCodeView) ? _L("Enter the move you want to jump to") + ":" : _L("Enter the height you want to jump to") + ":"; - wxString msg_header = (mode == dmSequentialGCodeView) ? _L("Jump to move") : _L("Jump to height"); - wxString msg_in = GUI::double_to_string(active_value); + wxString msg_text = _L("Enter the height you want to jump to") + ":"; + wxString msg_header = _L("Jump to height"); + wxString msg_in = GUI::double_to_string(active_value); // get custom gcode wxTextEntryDialog dlg(nullptr, msg_text, msg_header, msg_in, wxTextEntryDialogStyle); @@ -1379,7 +1187,7 @@ static double get_value_to_jump(double active_value, double min_z, double max_z, return dlg.GetValue().ToDouble(&value) ? value : -1.0; } -void Control::add_code_as_tick(Type type, int selected_extruder/* = -1*/) +void DSManagerForLayers::add_code_as_tick(Type type, int selected_extruder/* = -1*/) { const int tick = imgui_ctrl.GetActiveValue(); @@ -1413,7 +1221,7 @@ void Control::add_code_as_tick(Type type, int selected_extruder/* = -1*/) post_ticks_changed_event(type); } -void Control::add_current_tick(bool call_from_keyboard /*= false*/) +void DSManagerForLayers::add_current_tick(bool call_from_keyboard /*= false*/) { const int tick = imgui_ctrl.GetActiveValue(); auto it = m_ticks.ticks.find(TickCode{ tick }); @@ -1455,7 +1263,7 @@ void Control::add_current_tick(bool call_from_keyboard /*= false*/) */ } -void Control::delete_current_tick() +void DSManagerForLayers::delete_current_tick() { auto it = m_ticks.ticks.find(TickCode{ imgui_ctrl.GetActiveValue()}); if (it == m_ticks.ticks.end() || @@ -1467,7 +1275,7 @@ void Control::delete_current_tick() post_ticks_changed_event(type); } -void Control::edit_tick(int tick/* = -1*/) +void DSManagerForLayers::edit_tick(int tick/* = -1*/) { if (tick < 0) tick = imgui_ctrl.GetActiveValue(); @@ -1482,14 +1290,8 @@ void Control::edit_tick(int tick/* = -1*/) post_ticks_changed_event(type); } -// switch on/off one layer mode -void Control::switch_one_layer_mode() -{ - imgui_ctrl.CombineThumbs(!imgui_ctrl.IsCombineThumbs()); -} - // discard all custom changes on DoubleSlider -void Control::discard_all_thicks() +void DSManagerForLayers::discard_all_thicks() { m_ticks.ticks.clear(); imgui_ctrl.ResetValues(); @@ -1497,7 +1299,7 @@ void Control::discard_all_thicks() post_ticks_changed_event(); } -void Control::edit_extruder_sequence() +void DSManagerForLayers::edit_extruder_sequence() { if (!check_ticks_changed_event(ToolChange)) return; @@ -1558,7 +1360,7 @@ void Control::edit_extruder_sequence() post_ticks_changed_event(ToolChange); } -void Control::jump_to_value() +void DSManagerForLayers::jump_to_value() { double value = get_value_to_jump(m_values[imgui_ctrl.GetActiveValue()], m_values[imgui_ctrl.GetMinValue()], m_values[imgui_ctrl.GetMaxValue()], m_draw_mode); @@ -1573,14 +1375,13 @@ void Control::jump_to_value() SetLowerValue(tick_value); } -void Control::post_ticks_changed_event(Type type /*= Custom*/) +void DSManagerForLayers::post_ticks_changed_event(Type type /*= Custom*/) { // m_force_mode_apply = type != ToolChange; // It looks like this condition is no needed now. Leave it for the testing - - wxPostEvent(this->GetParent(), wxCommandEvent(wxCUSTOMEVT_TICKSCHANGED)); + process_ticks_changed(); } -bool Control::check_ticks_changed_event(Type type) +bool DSManagerForLayers::check_ticks_changed_event(Type type) { if ( m_ticks.mode == m_mode || (type != ColorChange && type != ToolChange) || @@ -1602,7 +1403,7 @@ bool Control::check_ticks_changed_event(Type type) _L("Are you sure you want to continue?"); //wxMessageDialog msg(this, message, _L("Notice"), wxYES_NO); - GUI::MessageDialog msg(this, message, _L("Notice"), wxYES_NO); + GUI::MessageDialog msg(nullptr, message, _L("Notice"), wxYES_NO); if (msg.ShowModal() == wxID_YES) { m_ticks.erase_all_ticks_with_code(ColorChange); post_ticks_changed_event(ColorChange); @@ -1622,7 +1423,7 @@ bool Control::check_ticks_changed_event(Type type) _L("Your current changes will delete all saved extruder (tool) changes.") + "\n\n\t" + _L("Are you sure you want to continue?") ) ; - GUI::MessageDialog msg(this, message, _L("Notice"), wxYES_NO | (m_mode == SingleExtruder ? wxCANCEL : 0)); + GUI::MessageDialog msg(nullptr, message, _L("Notice"), wxYES_NO | (m_mode == SingleExtruder ? wxCANCEL : 0)); const int answer = msg.ShowModal(); if (answer == wxID_YES) { m_ticks.erase_all_ticks_with_code(ToolChange); @@ -1638,6 +1439,25 @@ bool Control::check_ticks_changed_event(Type type) return true; } +DSManagerForLayers::DSManagerForLayers( int lowerValue, + int higherValue, + int minValue, + int maxValue, + bool allow_editing/* = true*/) : + m_allow_editing(allow_editing) +{ +#ifdef __WXOSX__ + is_osx = true; +#endif //__WXOSX__ + Init(lowerValue, higherValue, minValue, maxValue, "layers_slider", false); + + imgui_ctrl.set_get_label_on_move_cb([this](int pos) { return m_show_estimated_times ? into_u8(get_label(pos, ltEstimatedTime)) : ""; }); + imgui_ctrl.set_extra_draw_cb([this](const ImRect& draw_rc) {return draw_ticks(draw_rc); }); + + m_ticks.set_pause_print_msg(_u8L("Place bearings in slots and resume printing")); + m_ticks.set_extruder_colors(&m_extruder_colors); +} + std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int extruder) { auto opposite_one_color = [](const std::string& color) { diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSlider.hpp index 74e4f2e08b..5a4c08d701 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSlider.hpp @@ -6,16 +6,8 @@ #define slic3r_GUI_DoubleSlider_hpp_ #include "libslic3r/CustomGCode.hpp" -#include "wxExtensions.hpp" -#include "GLCanvas3D.hpp" - #include "ImGuiDoubleSlider.hpp" -#include -#include -#include -#include - #include #include @@ -45,9 +37,6 @@ bool check_color_change(const PrintObject* object, size_t frst_layer_id, size_t // and return true when detection have to be desturbed std::function break_condition); -// custom message the slider sends to its parent to notify a tick-change: -wxDECLARE_EVENT(wxCUSTOMEVT_TICKSCHANGED, wxEvent); - enum FocusedItem { fiNone, @@ -90,7 +79,6 @@ enum DrawMode dmRegular, dmSlaPrint, dmSequentialFffPrint, - dmSequentialGCodeView, }; enum LabelType @@ -204,65 +192,164 @@ struct ExtrudersSequence } }; -class Control : public wxControl +template +class DSManager_t { public: - Control( - wxWindow *parent, - int lowerValue, - int higherValue, - int minValue, - int maxValue, - long style = wxSL_VERTICAL, - const wxString& name = wxEmptyString); - ~Control() {} + + void Init( int lowerValue, + int higherValue, + int minValue, + int maxValue, + const std::string& name, + bool is_horizontal) + { + imgui_ctrl = ImGuiControl( lowerValue, higherValue, + minValue, maxValue, + is_horizontal ? 0 : ImGuiSliderFlags_Vertical, + name, !is_horizontal); + + imgui_ctrl.set_get_label_cb([this](int pos) {return get_label(pos); }); + }; + + DSManager_t() {} + DSManager_t(int lowerValue, + int higherValue, + int minValue, + int maxValue, + const std::string& name, + bool is_horizontal) + { + Init (lowerValue, higherValue, minValue, maxValue, name, is_horizontal); + } + ~DSManager_t() {} int GetMinValue() const { return imgui_ctrl.GetMinValue(); } int GetMaxValue() const { return imgui_ctrl.GetMaxValue(); } - double GetMinValueD() { return m_values.empty() ? 0. : m_values[GetMinValue()]; } - double GetMaxValueD() { return m_values.empty() ? 0. : m_values[GetMaxValue()]; } int GetLowerValue() const { return imgui_ctrl.GetLowerValue(); } int GetHigherValue()const { return imgui_ctrl.GetHigherValue(); } - double GetLowerValueD() { return get_double_value(ssLower); } - double GetHigherValueD() { return get_double_value(ssHigher); } + + ValType GetMinValueD() { return m_values.empty() ? static_cast(0) : m_values[GetMinValue()]; } + ValType GetMaxValueD() { return m_values.empty() ? static_cast(0) : m_values[GetMaxValue()]; } + ValType GetLowerValueD() { return m_values.empty() ? static_cast(0) : m_values[GetLowerValue()];} + ValType GetHigherValueD() { return m_values.empty() ? static_cast(0) : m_values[GetHigherValue()]; } // Set low and high slider position. If the span is non-empty, disable the "one layer" mode. - void SetLowerValue (const int lower_val); - void SetHigherValue(const int higher_val); - void SetSelectionSpan(const int lower_val, const int higher_val); + void SetLowerValue(const int lower_val) { + imgui_ctrl.SetLowerValue(lower_val); + process_thumb_move(); + } + void SetHigherValue(const int higher_val) { + imgui_ctrl.SetHigherValue(higher_val); + process_thumb_move(); + } + void SetSelectionSpan(const int lower_val, const int higher_val) { + imgui_ctrl.SetSelectionSpan(lower_val, higher_val); + process_thumb_move(); + } + void SetMaxValue(const int max_value) { + imgui_ctrl.SetMaxValue(max_value); + process_thumb_move(); + } - void SetMaxValue(const int max_value); - void SetSliderValues(const std::vector& values); - void ChangeOneLayerLock(); - void SetSliderAlternateValues(const std::vector& values) { m_alternate_values = values; } - - Info GetTicksValues() const; - void SetTicksValues(const Info &custom_gcode_per_print_z); - void SetLayersTimes(const std::vector& layers_times, float total_time); - void SetLayersTimes(const std::vector& layers_times); - - void SetDrawMode(bool is_sla_print, bool is_sequential_print); - void SetDrawMode(DrawMode mode) { m_draw_mode = mode; } - - void SetManipulationMode(Mode mode) { m_mode = mode; } - Mode GetManipulationMode() const { return m_mode; } - void SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder); - void SetExtruderColors(const std::vector& extruder_colors); - - bool IsNewPrint(); - - void set_render_as_disabled(bool value) { m_render_as_disabled = value; } - bool is_rendering_as_disabled() const { return m_render_as_disabled; } + void SetSliderValues(const std::vector& values) { m_values = values; } + // values used to show thumb labels + void SetSliderAlternateValues(const std::vector& values) { m_alternate_values = values; } bool is_lower_at_min() const { return imgui_ctrl.is_lower_at_min(); } bool is_higher_at_max() const { return imgui_ctrl.is_higher_at_max(); } - void UseDefaultColors(bool def_colors_on); - void OnKeyDown(wxKeyEvent &event); - void OnChar(wxKeyEvent &event); + void Show(bool show = true) { imgui_ctrl.Show(show); } + void Hide() { Show(false); } - bool Show(bool show = true) override { imgui_ctrl.Show(show); return true; } - bool Hide() { return Show(false); } + virtual void imgui_render(const int canvas_width, const int canvas_height, float extra_scale = 1.f) = 0; + + void set_callback_on_thumb_move(std::function cb) { m_cb_thumb_move = cb; }; + + void move_current_thumb(const int delta) + { + imgui_ctrl.MoveActiveThumb(delta); + process_thumb_move(); + } + +protected: + + std::vector m_values; + std::vector m_alternate_values; + + GUI::ImGuiControl imgui_ctrl; + float m_scale{ 1.f }; + + std::string get_label(int pos) const { + if (m_values.empty()) + return GUI::format("%1%", pos); + if (pos >= m_values.size()) + return "ErrVal"; + return GUI::format("%1%", static_cast(m_alternate_values.empty() ? m_values[pos] : m_alternate_values[pos])); + } + + void process_thumb_move() { + if (m_cb_thumb_move) + m_cb_thumb_move(); + } + +private: + + std::function m_cb_thumb_move{ nullptr }; +}; + + +class DSManagerForGcode : public DSManager_t +{ +public: + DSManagerForGcode() : DSManager_t() {} + DSManagerForGcode( int lowerValue, + int higherValue, + int minValue, + int maxValue) + { + Init(lowerValue, higherValue, minValue, maxValue, "moves_slider", true); + } + ~DSManagerForGcode() {} + + void imgui_render(const int canvas_width, const int canvas_height, float extra_scale = 1.f) override; + + void set_render_as_disabled(bool value) { m_render_as_disabled = value; } + bool is_rendering_as_disabled() const { return m_render_as_disabled; } + +private: + + bool m_render_as_disabled{ false }; +}; + + + +class DSManagerForLayers : public DSManager_t +{ +public: + DSManagerForLayers() : DSManager_t() {} + DSManagerForLayers( int lowerValue, + int higherValue, + int minValue, + int maxValue, + bool allow_editing = true); + ~DSManagerForLayers() {} + + void ChangeOneLayerLock(); + + Info GetTicksValues() const; + void SetTicksValues(const Info& custom_gcode_per_print_z); + void SetLayersTimes(const std::vector& layers_times, float total_time); + void SetLayersTimes(const std::vector& layers_times); + + void SetDrawMode(bool is_sla_print, bool is_sequential_print); + + void SetManipulationMode(Mode mode) { m_mode = mode; } + Mode GetManipulationMode() const { return m_mode; } + void SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder); + void SetExtruderColors(const std::vector& extruder_colors); + + void UseDefaultColors(bool def_colors_on); void add_code_as_tick(Type type, int selected_extruder = -1); // add default action for tick, when press "+" @@ -270,31 +357,36 @@ public: // delete current tick, when press "-" void delete_current_tick(); void edit_tick(int tick = -1); - void switch_one_layer_mode(); void discard_all_thicks(); void edit_extruder_sequence(); - void jump_to_value(); void enable_action_icon(bool enable) { m_enable_action_icon = enable; } void show_cog_icon_context_menu(); void auto_color_change(); + void jump_to_value(); - void imgui_render(GUI::GLCanvas3D& canvas, float extra_scale = 1.f); + void set_callback_on_ticks_changed(std::function cb) { m_cb_ticks_changed = cb; }; + + void imgui_render(const int canvas_width, const int canvas_height, float extra_scale = 1.f) override; + + bool IsNewPrint(const std::string& print_obj_idxs); private: - bool is_lower_thumb_editable(); - void move_current_thumb(const bool condition); bool is_wipe_tower_layer(int tick) const; - wxString get_label(int tick, LabelType label_type = ltHeightWithLayer) const; + std::string get_label(int tick, LabelType label_type = ltHeightWithLayer) const; - double get_double_value(const SelectedSlider& selection); int get_tick_from_value(double value, bool force_lower_bound = false); wxString get_tooltip(int tick = -1); 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; + void process_ticks_changed() { + if (m_cb_ticks_changed) + m_cb_ticks_changed(); + } + // Get active extruders for tick. // Means one current extruder for not existing tick OR // 2 extruders - for existing tick (extruder before ToolChangeCode and extruder of current existing tick) @@ -304,19 +396,17 @@ private: void post_ticks_changed_event(Type type = Custom); bool check_ticks_changed_event(Type type); - void append_change_extruder_menu_item (wxMenu*, bool switch_current_code = false); + void append_change_extruder_menu_item(wxMenu*, bool switch_current_code = false); void append_add_color_change_menu_item(wxMenu*, bool switch_current_code = false); - bool is_osx { false }; - - bool m_render_as_disabled{ false }; + bool is_osx{ false }; bool m_allow_editing{ true }; bool m_force_mode_apply = true; bool m_enable_action_icon = true; bool m_is_wipe_tower = false; //This flag indicates that there is multiple extruder print with wipe tower - DrawMode m_draw_mode = dmRegular; + DrawMode m_draw_mode { dmRegular }; Mode m_mode = SingleExtruder; int m_only_extruder = -1; @@ -326,19 +416,18 @@ private: bool m_show_estimated_times{ false }; - std::vector m_values; TickCodeInfo m_ticks; std::vector m_layers_times; std::vector m_layers_values; std::vector m_extruder_colors; - std::string m_print_obj_idxs; - - std::vector m_alternate_values; ExtrudersSequence m_extruders_sequence; + std::function m_cb_ticks_changed{ nullptr }; + + std::string m_print_obj_idxs; + // ImGuiDS - float m_scale{ 1.f }; bool m_can_change_color{ true }; void draw_colored_band(const ImRect& groove, const ImRect& slideable_region); @@ -346,8 +435,6 @@ private: void render_menu(); bool render_button(const wchar_t btn_icon, const wchar_t btn_icon_hovered, const std::string& label_id, const ImVec2& pos, FocusedItem focus, int tick = -1); void update_callbacks(); - - GUI::ImGuiControl imgui_ctrl; }; } // DoubleSlider; diff --git a/src/slic3r/GUI/ExtruderSequenceDialog.hpp b/src/slic3r/GUI/ExtruderSequenceDialog.hpp index 61cd057425..37046834af 100644 --- a/src/slic3r/GUI/ExtruderSequenceDialog.hpp +++ b/src/slic3r/GUI/ExtruderSequenceDialog.hpp @@ -7,6 +7,7 @@ #include "GUI_Utils.hpp" #include "DoubleSlider.hpp" +#include "wxExtensions.hpp" class wxTextCtrl; class wxFlexGridSizer; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 28cf4f0d7b..7c111d63c5 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -77,7 +77,6 @@ #include #include #include -#include "DoubleSlider.hpp" #include #include @@ -1019,9 +1018,7 @@ wxDEFINE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_BED_SHAPE, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_RESETGIZMOS, SimpleEvent); -wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_SLIDERS, wxKeyEvent); -wxDEFINE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); -wxDEFINE_EVENT(EVT_GLCANVAS_JUMP_TO, wxKeyEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_SLIDERS_MANIPULATION, wxKeyEvent); wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_COLLAPSE_SIDEBAR, SimpleEvent); @@ -2828,14 +2825,14 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case '6': { select_view("right"); break; } case '+': { if (dynamic_cast(m_canvas->GetParent()) != nullptr) - post_event(wxKeyEvent(EVT_GLCANVAS_EDIT_COLOR_CHANGE, evt)); + post_event(wxKeyEvent(EVT_GLCANVAS_SLIDERS_MANIPULATION, evt)); else post_event(Event(EVT_GLCANVAS_INCREASE_INSTANCES, +1)); break; } case '-': { if (dynamic_cast(m_canvas->GetParent()) != nullptr) - post_event(wxKeyEvent(EVT_GLCANVAS_EDIT_COLOR_CHANGE, evt)); + post_event(wxKeyEvent(EVT_GLCANVAS_SLIDERS_MANIPULATION, evt)); else post_event(Event(EVT_GLCANVAS_INCREASE_INSTANCES, -1)); break; @@ -2853,7 +2850,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case 'g': { if ((evt.GetModifiers() & shiftMask) != 0) { if (dynamic_cast(m_canvas->GetParent()) != nullptr) - post_event(wxKeyEvent(EVT_GLCANVAS_JUMP_TO, evt)); + post_event(wxKeyEvent(EVT_GLCANVAS_SLIDERS_MANIPULATION, evt)); } break; } @@ -3138,7 +3135,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) keyCode == WXK_UP || keyCode == WXK_DOWN) { if (dynamic_cast(m_canvas->GetParent()) != nullptr) - post_event(wxKeyEvent(EVT_GLCANVAS_MOVE_SLIDERS, evt)); + post_event(wxKeyEvent(EVT_GLCANVAS_SLIDERS_MANIPULATION, evt)); } } } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 01d10032ba..ccc29d4b84 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -176,9 +176,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_BED_SHAPE, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_RESETGIZMOS, SimpleEvent); -wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_SLIDERS, wxKeyEvent); -wxDECLARE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); -wxDECLARE_EVENT(EVT_GLCANVAS_JUMP_TO, wxKeyEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_SLIDERS_MANIPULATION, wxKeyEvent); wxDECLARE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_COLLAPSE_SIDEBAR, SimpleEvent); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 35b1e3b284..e3a9aadfef 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -231,14 +231,11 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model) m_canvas->show_legend(true); m_canvas->enable_dynamic_background(true); - create_layers_slider(); + create_sliders(); m_left_sizer = new wxBoxSizer(wxVERTICAL); m_left_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0); - m_moves_slider = new DoubleSlider::Control(this, 0, 0, 0, 100, wxSL_HORIZONTAL, "moves_slider"); - m_moves_slider->SetDrawMode(DoubleSlider::dmSequentialGCodeView); - wxBoxSizer* main_sizer = new wxBoxSizer(wxHORIZONTAL); main_sizer->Add(m_left_sizer, 1, wxALL | wxEXPAND, 0); @@ -260,6 +257,11 @@ Preview::~Preview() if (m_canvas_widget != nullptr) delete m_canvas_widget; + + if (m_layers_slider) + delete m_layers_slider; + if (m_moves_slider) + delete m_moves_slider; } void Preview::set_as_dirty() @@ -321,42 +323,24 @@ void Preview::msw_rescale() void Preview::render_sliders(GLCanvas3D& canvas, float extra_scale/* = 0.1f*/) { + const Size cnv_size = canvas.get_canvas_size(); + const int canvas_width = cnv_size.get_width(); + const int canvas_height = cnv_size.get_height(); + if (m_layers_slider) - m_layers_slider->imgui_render(canvas, extra_scale); + m_layers_slider->imgui_render(canvas_width, canvas_height, extra_scale); if (m_moves_slider) - m_moves_slider->imgui_render(canvas, extra_scale); -} - -void Preview::jump_layers_slider(wxKeyEvent& evt) -{ - if (m_layers_slider) m_layers_slider->OnChar(evt); -} - -void Preview::move_layers_slider(wxKeyEvent& evt) -{ - if (m_layers_slider != nullptr) m_layers_slider->OnKeyDown(evt); -} - -void Preview::edit_layers_slider(wxKeyEvent& evt) -{ - if (m_layers_slider != nullptr) m_layers_slider->OnChar(evt); + m_moves_slider->imgui_render(canvas_width, canvas_height, extra_scale); } void Preview::bind_event_handlers() { Bind(wxEVT_SIZE, &Preview::on_size, this); - m_moves_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this); } void Preview::unbind_event_handlers() { Unbind(wxEVT_SIZE, &Preview::on_size, this); - m_moves_slider->Unbind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this); -} - -void Preview::move_moves_slider(wxKeyEvent& evt) -{ - if (m_moves_slider != nullptr) m_moves_slider->OnKeyDown(evt); } void Preview::hide_layers_slider() @@ -370,26 +354,20 @@ void Preview::on_size(wxSizeEvent& evt) Refresh(); } -void Preview::create_layers_slider() +void Preview::create_sliders() { - m_layers_slider = new DoubleSlider::Control(this,0, 0, 0, 100, wxVERTICAL, "layers_slider"); + // Layers Slider + + m_layers_slider = new DoubleSlider::DSManagerForLayers(0, 0, 0, 100, wxGetApp().is_editor()); m_layers_slider->SetDrawMode(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA, - wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects")); + wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects")); m_layers_slider->enable_action_icon(wxGetApp().is_editor()); - // sizer, m_canvas_widget - m_canvas_widget->Bind(wxEVT_KEY_DOWN, &Preview::update_layers_slider_from_canvas, this); - m_canvas_widget->Bind(wxEVT_KEY_UP, [this](wxKeyEvent& event) { - if (event.GetKeyCode() == WXK_SHIFT) - m_layers_slider->UseDefaultColors(true); - event.Skip(); - }); + m_layers_slider->set_callback_on_thumb_move( [this]() -> void { Preview::on_layers_slider_scroll_changed(); } ); - m_layers_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_layers_slider_scroll_changed, this); - - Bind(DoubleSlider::wxCUSTOMEVT_TICKSCHANGED, [this](wxEvent&) { + m_layers_slider->set_callback_on_ticks_changed( [this]() -> void { Model& model = wxGetApp().plater()->model(); model.custom_gcode_per_print_z = m_layers_slider->GetTicksValues(); m_schedule_background_process(); @@ -397,6 +375,16 @@ void Preview::create_layers_slider() m_keep_current_preview_type = false; reload_print(); }); + + // Move Gcode Slider + + m_moves_slider = new DoubleSlider::DSManagerForGcode(0, 0, 0, 100); + + m_moves_slider->set_callback_on_thumb_move([this]() ->void { Preview::on_moves_slider_scroll_changed(); }); + + // m_canvas_widget + m_canvas_widget->Bind(wxEVT_KEY_DOWN, &Preview::update_sliders_from_canvas, this); + m_canvas_widget->Bind(EVT_GLCANVAS_SLIDERS_MANIPULATION, &Preview::update_sliders_from_canvas, this); } // Find an index of a value in a sorted vector, which is in . @@ -510,10 +498,20 @@ void Preview::update_layers_slider(const std::vector& layers_z, bool kee break; } + auto get_print_obj_idxs = [plater]() ->std::string { + if (plater->printer_technology() == ptSLA) + return "sla"; + const Print& print = GUI::wxGetApp().plater()->fff_print(); + std::string idxs; + for (auto object : print.objects()) + idxs += std::to_string(object->id().id) + "_"; + return idxs; + }; + // Suggest the auto color change, if model looks like sign if (!color_change_already_exists && wxGetApp().app_config->get_bool("allow_auto_color_change") && - m_layers_slider->IsNewPrint()) + m_layers_slider->IsNewPrint(get_print_obj_idxs())) { const Print& print = wxGetApp().plater()->fff_print(); @@ -631,16 +629,39 @@ void Preview::reset_layers_slider() m_layers_slider->SetLowerValue(0); } -void Preview::update_layers_slider_from_canvas(wxKeyEvent& event) +void Preview::update_sliders_from_canvas(wxKeyEvent& event) { - if (event.HasModifiers()) { + const auto key = event.GetKeyCode(); + + if (key == WXK_NUMPAD_ADD || key == '+') + m_layers_slider->add_current_tick(true); + else if (key == WXK_NUMPAD_SUBTRACT || key == WXK_DELETE || key == WXK_BACK || key == '-') + m_layers_slider->delete_current_tick(); + else if (key == 'G' || key == 'g') + m_layers_slider->jump_to_value(); + else if (key == WXK_LEFT || key == WXK_RIGHT || key == WXK_UP || key == WXK_DOWN) { + int delta = 1; + // accelerators + int accelerator = 0; + if (wxGetKeyState(WXK_SHIFT)) + accelerator += 5; + if (wxGetKeyState(WXK_CONTROL)) + accelerator += 5; + if (accelerator > 0) + delta *= accelerator; + + if (key == WXK_LEFT || key == WXK_RIGHT) + m_moves_slider->move_current_thumb(delta * (key == WXK_LEFT ? 1 : -1)); + else if (key == WXK_UP || key == WXK_DOWN) + m_layers_slider->move_current_thumb(delta * (key == WXK_DOWN ? 1 : -1)); + } + + else if (event.HasModifiers()) { event.Skip(); return; } - const auto key = event.GetKeyCode(); - - if (key == 'S' || key == 'W') { + else if (key == 'S' || key == 'W') { const int new_pos = key == 'W' ? m_layers_slider->GetHigherValue() + 1 : m_layers_slider->GetHigherValue() - 1; m_layers_slider->SetHigherValue(new_pos); } @@ -650,8 +671,6 @@ void Preview::update_layers_slider_from_canvas(wxKeyEvent& event) } else if (key == 'X') m_layers_slider->ChangeOneLayerLock(); - else if (key == WXK_SHIFT) - m_layers_slider->UseDefaultColors(false); else event.Skip(); } @@ -669,9 +688,9 @@ void Preview::update_moves_slider(std::optional visible_range_min, std::opt std::optional{ m_canvas->get_gcode_vertex_at(*visible_range_max).gcode_id } : std::nullopt; const size_t range_size = range[1] - range[0] + 1; - std::vector values; + std::vector values; values.reserve(range_size); - std::vector alternate_values; + std::vector alternate_values; alternate_values.reserve(range_size); std::optional visible_range_min_id; @@ -684,7 +703,7 @@ void Preview::update_moves_slider(std::optional visible_range_min, std::opt if (i > range[0]) { // skip consecutive moves with same gcode id (resulting from processing G2 and G3 lines) if (last_gcode_id == gcode_id) { - values.back() = static_cast(i + 1); + values.back() = i + 1; skip = true; } else @@ -692,11 +711,11 @@ void Preview::update_moves_slider(std::optional visible_range_min, std::opt } if (!skip) { - values.emplace_back(static_cast(i + 1)); - alternate_values.emplace_back(static_cast(gcode_id)); - if (gcode_id_min.has_value() && alternate_values.back() == static_cast(*gcode_id_min)) + values.emplace_back(i + 1); + alternate_values.emplace_back(gcode_id); + if (gcode_id_min.has_value() && alternate_values.back() == *gcode_id_min) visible_range_min_id = counter; - else if (gcode_id_max.has_value() && alternate_values.back() == static_cast(*gcode_id_max)) + else if (gcode_id_max.has_value() && alternate_values.back() == *gcode_id_max) visible_range_max_id = counter; ++counter; } @@ -716,7 +735,6 @@ void Preview::enable_moves_slider(bool enable) bool render_as_disabled = !enable; if (m_moves_slider != nullptr && m_moves_slider->is_rendering_as_disabled() != render_as_disabled) { m_moves_slider->set_render_as_disabled(render_as_disabled); - m_moves_slider->Refresh(); } } @@ -865,7 +883,7 @@ void Preview::load_print_as_sla() } } -void Preview::on_layers_slider_scroll_changed(wxCommandEvent& event) +void Preview::on_layers_slider_scroll_changed() { if (IsShown()) { PrinterTechnology tech = m_process->current_printer_technology(); @@ -882,7 +900,7 @@ void Preview::on_layers_slider_scroll_changed(wxCommandEvent& event) } } -void Preview::on_moves_slider_scroll_changed(wxCommandEvent& event) +void Preview::on_moves_slider_scroll_changed() { m_canvas->update_gcode_sequential_view_current(static_cast(m_moves_slider->GetLowerValueD() - 1.0), static_cast(m_moves_slider->GetHigherValueD() - 1.0)); m_canvas->set_as_dirty(); diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 90484a8a0b..452185fbe1 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -28,7 +28,8 @@ class BackgroundSlicingProcess; class Model; namespace DoubleSlider { - class Control; + class DSManagerForGcode; + class DSManagerForLayers; }; namespace GUI { @@ -95,8 +96,8 @@ class Preview : public wxPanel bool m_loaded { false }; - DoubleSlider::Control* m_layers_slider{ nullptr }; - DoubleSlider::Control* m_moves_slider{ nullptr }; + DoubleSlider::DSManagerForLayers* m_layers_slider{ nullptr }; + DoubleSlider::DSManagerForGcode* m_moves_slider { nullptr }; public: enum class OptionType : unsigned int @@ -133,9 +134,6 @@ public: void reload_print(); void msw_rescale(); - void jump_layers_slider(wxKeyEvent& evt); - void move_layers_slider(wxKeyEvent& evt); - void edit_layers_slider(wxKeyEvent& evt); void render_sliders(GLCanvas3D& canvas, float extra_scale = 0.1f); @@ -143,7 +141,6 @@ public: void update_moves_slider(std::optional visible_range_min = std::nullopt, std::optional visible_range_max = std::nullopt); void enable_moves_slider(bool enable); - void move_moves_slider(wxKeyEvent& evt); void hide_layers_slider(); void set_keep_current_preview_type(bool value) { m_keep_current_preview_type = value; } @@ -159,20 +156,20 @@ private: void on_size(wxSizeEvent& evt); // Create/Update/Reset double slider on 3dPreview - void create_layers_slider(); + void create_sliders(); void check_layers_slider_values(std::vector& ticks_from_model, const std::vector& layers_z); void reset_layers_slider(); void update_layers_slider(const std::vector& layers_z, bool keep_z_range = false); void update_layers_slider_mode(); // update vertical DoubleSlider after keyDown in canvas - void update_layers_slider_from_canvas(wxKeyEvent& event); + void update_sliders_from_canvas(wxKeyEvent& event); void load_print_as_fff(bool keep_z_range = false); void load_print_as_sla(); - void on_layers_slider_scroll_changed(wxCommandEvent& event); - void on_moves_slider_scroll_changed(wxCommandEvent& event); + void on_layers_slider_scroll_changed(); + void on_moves_slider_scroll_changed(); }; } // namespace GUI diff --git a/src/slic3r/GUI/ImGuiDoubleSlider.cpp b/src/slic3r/GUI/ImGuiDoubleSlider.cpp index ab65590d80..9befb33b87 100644 --- a/src/slic3r/GUI/ImGuiDoubleSlider.cpp +++ b/src/slic3r/GUI/ImGuiDoubleSlider.cpp @@ -120,14 +120,10 @@ ImGuiControl::ImGuiControl( int lowerValue, int higherValue, int minValue, int maxValue, - ImVec2 pos, - ImVec2 size, ImGuiSliderFlags flags, std::string name, bool use_lower_thumb) : m_selection(ssUndef), - m_pos(pos), - m_size(size), m_name(name), m_lower_value(lowerValue), m_higher_value (higherValue), diff --git a/src/slic3r/GUI/ImGuiDoubleSlider.hpp b/src/slic3r/GUI/ImGuiDoubleSlider.hpp index 425a33d8c7..b2f2263707 100644 --- a/src/slic3r/GUI/ImGuiDoubleSlider.hpp +++ b/src/slic3r/GUI/ImGuiDoubleSlider.hpp @@ -32,13 +32,6 @@ enum SelectedSlider { ssHigher }; -enum LabelType -{ - ltHeightWithLayer, - ltHeight, - ltEstimatedTime, -}; - class ImGuiControl { public: @@ -46,8 +39,6 @@ public: int higherValue, int minValue, int maxValue, - ImVec2 pos, - ImVec2 size, ImGuiSliderFlags flags = ImGuiSliderFlags_None, std::string name = "d_slider", bool use_lower_thumb = true); @@ -79,12 +70,12 @@ public: m_draw_opts.scale = scale; } - void Show(bool show) { m_is_shown = show; } - void Hide() { m_is_shown = false; } - bool IsShown() const { return m_is_shown; } - void MoveActiveThumb(int delta); - bool IsCombineThumbs() const { return m_combine_thumbs; } - bool IsActiveHigherThumb() const { return m_selection == ssHigher; } + void Show(bool show) { m_is_shown = show; } + void Hide() { m_is_shown = false; } + bool IsShown() const { return m_is_shown; } + bool IsCombineThumbs() const { return m_combine_thumbs; } + bool IsActiveHigherThumb() const { return m_selection == ssHigher; } + void MoveActiveThumb(int delta); void ShowLabelOnMouseMove(bool show = true) { m_show_move_label = show; } ImRect GetGrooveRect() const { return m_draw_opts.groove(m_pos, m_size, is_horizontal()); } @@ -95,11 +86,7 @@ public: bool is_full_span() const { return this->is_lower_at_min() && this->is_higher_at_max(); } bool is_rclick_on_thumb() const { return m_rclick_on_selected_thumb; } - void correct_lower_value(); - void correct_higher_value(); - bool render(); - void draw_scroll_line(const ImRect& scroll_line, const ImRect& slideable_region); std::string get_label(int pos) const; @@ -108,6 +95,8 @@ public: void set_draw_scroll_line_cb(std::function cb) { m_cb_draw_scroll_line = cb; } void set_extra_draw_cb(std::function cb) { m_cb_extra_draw = cb; } +private: + struct DrawOptions { float scale { 1.f }; // used for Retina on osx @@ -134,8 +123,6 @@ public: ImRect lower_thumb; }; -private: - SelectedSlider m_selection; ImVec2 m_pos; ImVec2 m_size; @@ -143,31 +130,34 @@ private: ImGuiSliderFlags m_flags{ ImGuiSliderFlags_None }; bool m_is_shown{ true }; - int m_min_value; - int m_max_value; - int m_lower_value; - int m_higher_value; - int m_mouse_pos_value; + int m_min_value; + int m_max_value; + int m_lower_value; + int m_higher_value; + int m_mouse_pos_value; - bool m_rclick_on_selected_thumb{ false }; + bool m_rclick_on_selected_thumb{ false }; - bool m_draw_lower_thumb{ true }; - bool m_combine_thumbs { false }; - bool m_show_move_label{ false }; + bool m_draw_lower_thumb{ true }; + bool m_combine_thumbs { false }; + bool m_show_move_label { false }; - DrawOptions m_draw_opts; - Regions m_regions; + DrawOptions m_draw_opts; + Regions m_regions; std::function m_cb_get_label { nullptr }; std::function m_cb_get_label_on_move { nullptr }; std::function m_cb_draw_scroll_line { nullptr }; std::function m_cb_extra_draw { nullptr }; - void apply_regions(int higher_value, int lower_value, const ImRect& draggable_region); + void correct_lower_value(); + void correct_higher_value(); std::string get_label_on_move(int pos) const { return m_cb_get_label_on_move ? m_cb_get_label_on_move(pos) : get_label(pos); } + void apply_regions(int higher_value, int lower_value, const ImRect& draggable_region); void check_and_correct_thumbs(int* higher_value, int* lower_value); + void draw_scroll_line(const ImRect& scroll_line, const ImRect& slideable_region); void draw_background(const ImRect& slideable_region); void draw_label(std::string label, const ImRect& thumb); void draw_thumb(const ImVec2& center, bool mark = false); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index da95c696c2..73f3d7af20 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -736,12 +736,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); }); preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_COLLAPSE_SIDEBAR, [this](SimpleEvent&) { this->q->collapse_sidebar(!this->q->is_sidebar_collapsed()); }); } - preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_JUMP_TO, [this](wxKeyEvent& evt) { preview->jump_layers_slider(evt); }); - preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_MOVE_SLIDERS, [this](wxKeyEvent& evt) { - preview->move_layers_slider(evt); - preview->move_moves_slider(evt); - }); - preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_EDIT_COLOR_CHANGE, [this](wxKeyEvent& evt) { preview->edit_layers_slider(evt); }); + if (wxGetApp().is_gcode_viewer()) preview->Bind(EVT_GLCANVAS_RELOAD_FROM_DISK, [this](SimpleEvent&) { this->q->reload_gcode_from_disk(); });