diff --git a/resources/localization/list.txt b/resources/localization/list.txt index 8acf52612d..9d8429f41c 100644 --- a/resources/localization/list.txt +++ b/resources/localization/list.txt @@ -30,7 +30,7 @@ src/slic3r/GUI/ConfigManipulation.cpp src/slic3r/GUI/ConfigSnapshotDialog.cpp src/slic3r/GUI/ConfigWizard.cpp src/slic3r/GUI/DesktopIntegrationDialog.cpp -src/slic3r/GUI/DoubleSlider.cpp +src/slic3r/GUI/DoubleSliderForLayers.cpp src/slic3r/GUI/Downloader.cpp src/slic3r/GUI/DownloaderFileGet.cpp src/slic3r/GUI/EditGCodeDialog.cpp diff --git a/src/libslic3r/CustomGCode.hpp b/src/libslic3r/CustomGCode.hpp index 939f8bdd51..a78fdb05ad 100644 --- a/src/libslic3r/CustomGCode.hpp +++ b/src/libslic3r/CustomGCode.hpp @@ -14,6 +14,11 @@ class DynamicPrintConfig; namespace CustomGCode { +/* For exporting GCode in GCodeWriter is used XYZF_NUM(val) = PRECISION(val, 3) for XYZ values. + * So, let use same value as a permissible error for layer height. + */ +constexpr double epsilon() { return 0.0011; } + enum Type { ColorChange, diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 89f094d448..f877148a03 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -252,10 +252,12 @@ set(SLIC3R_GUI_SOURCES GUI/ProgressStatusBar.cpp GUI/Mouse3DController.cpp GUI/Mouse3DController.hpp - GUI/DoubleSlider.cpp - GUI/DoubleSlider.hpp GUI/ImGuiDoubleSlider.cpp GUI/ImGuiDoubleSlider.hpp + GUI/DoubleSliderForLayers.cpp + GUI/DoubleSliderForLayers.hpp + GUI/DoubleSliderForGcode.cpp + GUI/DoubleSliderForGcode.hpp GUI/Notebook.cpp GUI/Notebook.hpp GUI/TopBar.cpp diff --git a/src/slic3r/GUI/DoubleSliderForGcode.cpp b/src/slic3r/GUI/DoubleSliderForGcode.cpp new file mode 100644 index 0000000000..65e8663b1d --- /dev/null +++ b/src/slic3r/GUI/DoubleSliderForGcode.cpp @@ -0,0 +1,33 @@ +///|/ Copyright (c) Prusa Research 2020 - 2023 Oleksandra Iushchenko @YuSanka, Vojtěch Bubník @bubnikv, Tomáš Mészáros @tamasmeszaros, Lukáš Matěna @lukasmatena, Enrico Turri @enricoturri1966 +///|/ +///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher +///|/ + +#include "DoubleSliderForGcode.hpp" + +namespace Slic3r { + +namespace DoubleSlider { + +static const float LEFT_MARGIN = 13.0f + 100.0f; // avoid thumbnail toolbar +static const float HORIZONTAL_SLIDER_HEIGHT = 90.0f; + +void DSForGcode::Render(const int canvas_width, const int canvas_height, float extra_scale/* = 0.1f*/) +{ + if (!m_ctrl.IsShown()) + return; + m_scale = extra_scale * 0.1f * m_em; + + ImVec2 pos = ImVec2{std::max(LEFT_MARGIN, 0.2f * canvas_width), canvas_height - HORIZONTAL_SLIDER_HEIGHT * m_scale}; + ImVec2 size = ImVec2(canvas_width - 2 * pos.x, HORIZONTAL_SLIDER_HEIGHT * m_scale); + + m_ctrl.Init(pos, size, m_scale); + if (m_ctrl.render()) + process_thumb_move(); +} + +} // DoubleSlider + +} // Slic3r + + diff --git a/src/slic3r/GUI/DoubleSliderForGcode.hpp b/src/slic3r/GUI/DoubleSliderForGcode.hpp new file mode 100644 index 0000000000..c830701637 --- /dev/null +++ b/src/slic3r/GUI/DoubleSliderForGcode.hpp @@ -0,0 +1,42 @@ +///|/ Copyright (c) Prusa Research 2020 - 2022 Vojtěch Bubník @bubnikv, Oleksandra Iushchenko @YuSanka, Enrico Turri @enricoturri1966, Lukáš Matěna @lukasmatena +///|/ +///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher +///|/ +#ifndef slic3r_GUI_DoubleSliderForGcode_hpp_ +#define slic3r_GUI_DoubleSliderForGcode_hpp_ + +#include "ImGuiDoubleSlider.hpp" + +namespace Slic3r { + +namespace DoubleSlider { + +class DSForGcode : public Manager +{ +public: + DSForGcode() : Manager() {} + DSForGcode( int lowerPos, + int higherPos, + int minPos, + int maxPos) + { + Init(lowerPos, higherPos, minPos, maxPos, "moves_slider", true); + } + ~DSForGcode() {} + + void 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 }; +}; + +} // DoubleSlider; + +} // Slic3r + + +#endif // slic3r_GUI_DoubleSliderForGcode_hpp_ diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSliderForLayers.cpp similarity index 84% rename from src/slic3r/GUI/DoubleSlider.cpp rename to src/slic3r/GUI/DoubleSliderForLayers.cpp index 0823a58977..ded272e298 100644 --- a/src/slic3r/GUI/DoubleSlider.cpp +++ b/src/slic3r/GUI/DoubleSliderForLayers.cpp @@ -2,8 +2,9 @@ ///|/ ///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher ///|/ +#include "DoubleSliderForLayers.hpp" + #include "libslic3r/libslic3r.h" -#include "DoubleSlider.hpp" #include "libslic3r/GCode.hpp" #include "GUI.hpp" #include "GUI_App.hpp" @@ -14,8 +15,6 @@ #include "libslic3r/AppConfig.hpp" #include "GUI_Utils.hpp" #include "MsgDialog.hpp" -#include "Tab.hpp" -#include "GUI_ObjectList.hpp" #include #include @@ -24,7 +23,7 @@ #include #include #include -#include "Field.hpp" + #include "format.hpp" #include "NotificationManager.hpp" @@ -44,9 +43,7 @@ namespace DoubleSlider { constexpr double min_delta_area = scale_(scale_(25)); // equal to 25 mm2 constexpr double miscalculation = scale_(scale_(1)); // equal to 1 mm2 -static const float LEFT_MARGIN = 13.0f + 100.0f; // avoid thumbnail toolbar -static const float HORIZONTAL_SLIDER_WIDTH = 90.0f; -static const float VERTICAL_SLIDER_HEIGHT = 105.0f; +static const float VERTICAL_SLIDER_WIDTH = 105.0f; bool equivalent_areas(const double& bottom_area, const double& top_area) { @@ -55,7 +52,7 @@ bool equivalent_areas(const double& bottom_area, const double& top_area) static std::string gcode(Type type) { - const PrintConfig& config = GUI::wxGetApp().plater()->fff_print().config(); + const PrintConfig& config = GUI::wxGetApp().plater()->fff_print().config(); // ! ys_FIXME switch (type) { case ColorChange: return config.color_change_gcode; case PausePrint: return config.pause_print_gcode; @@ -64,7 +61,26 @@ static std::string gcode(Type type) } } -int DSManagerForLayers::get_tick_from_value(double value, bool force_lower_bound/* = false*/) +DSForLayers::DSForLayers( int lowerValue, + int higherValue, + int minValue, + int maxValue, + bool allow_editing) : + m_allow_editing(allow_editing) +{ +#ifdef __WXOSX__ + is_osx = true; +#endif //__WXOSX__ + Init(lowerValue, higherValue, minValue, maxValue, "layers_slider", false); + + m_ctrl.set_get_label_on_move_cb([this](int pos) { return m_show_estimated_times ? into_u8(get_label(pos, ltEstimatedTime)) : ""; }); + m_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); +} + +int DSForLayers::get_tick_from_value(double value, bool force_lower_bound/* = false*/) { std::vector::iterator it; if (m_is_wipe_tower && !force_lower_bound) @@ -78,7 +94,7 @@ int DSManagerForLayers::get_tick_from_value(double value, bool force_lower_bound return int(it - m_values.begin()); } -Info DSManagerForLayers::GetTicksValues() const +Info DSForLayers::GetTicksValues() const { Info custom_gcode_per_print_z; std::vector& values = custom_gcode_per_print_z.gcodes; @@ -91,13 +107,12 @@ Info DSManagerForLayers::GetTicksValues() const values.emplace_back(CustomGCode::Item{ m_values[tick.tick], tick.type, tick.extruder, tick.color, tick.extra }); } - if (m_force_mode_apply) - custom_gcode_per_print_z.mode = m_mode; + custom_gcode_per_print_z.mode = m_mode; return custom_gcode_per_print_z; } -void DSManagerForLayers::SetTicksValues(const Info& custom_gcode_per_print_z) +void DSForLayers::SetTicksValues(const Info& custom_gcode_per_print_z) { if (m_values.empty()) { m_ticks.mode = m_mode; @@ -116,18 +131,18 @@ void DSManagerForLayers::SetTicksValues(const Info& custom_gcode_per_print_z) 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 - post_ticks_changed_event(); + process_ticks_changed(); // init extruder sequence in respect to the extruders count if (m_ticks.empty()) m_extruders_sequence.init(m_extruder_colors.size()); - update_callbacks(); + update_draw_scroll_line_cb(); if (custom_gcode_per_print_z.mode && !custom_gcode_per_print_z.gcodes.empty()) m_ticks.mode = custom_gcode_per_print_z.mode; } -void DSManagerForLayers::SetLayersTimes(const std::vector& layers_times, float total_time) +void DSForLayers::SetLayersTimes(const std::vector& layers_times, float total_time) { m_layers_times.clear(); if (layers_times.empty()) @@ -153,7 +168,7 @@ void DSManagerForLayers::SetLayersTimes(const std::vector& layers_times, } } -void DSManagerForLayers::SetLayersTimes(const std::vector& layers_times) +void DSForLayers::SetLayersTimes(const std::vector& layers_times) { m_is_wipe_tower = false; m_layers_times = layers_times; @@ -161,16 +176,16 @@ void DSManagerForLayers::SetLayersTimes(const std::vector& layers_times) m_layers_times[i] += m_layers_times[i - 1]; } -void DSManagerForLayers::SetDrawMode(bool is_sla_print, bool is_sequential_print) +void DSForLayers::SetDrawMode(bool is_sla_print, bool is_sequential_print) { m_draw_mode = is_sla_print ? dmSlaPrint : is_sequential_print ? dmSequentialFffPrint : dmRegular; - update_callbacks(); + update_draw_scroll_line_cb(); } -void DSManagerForLayers::SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder) +void DSForLayers::SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder) { m_mode = !is_one_extruder_printed_model ? MultiExtruder : only_extruder < 0 ? SingleExtruder : @@ -185,12 +200,12 @@ void DSManagerForLayers::SetModeAndOnlyExtruder(const bool is_one_extruder_print m_is_wipe_tower = m_mode != SingleExtruder; } -void DSManagerForLayers::SetExtruderColors( const std::vector& extruder_colors) +void DSForLayers::SetExtruderColors( const std::vector& extruder_colors) { m_extruder_colors = extruder_colors; } -bool DSManagerForLayers::IsNewPrint(const std::string& idxs) +bool DSForLayers::IsNewPrint(const std::string& idxs) { if (idxs == "sla" || idxs == m_print_obj_idxs) return false; @@ -199,17 +214,17 @@ bool DSManagerForLayers::IsNewPrint(const std::string& idxs) return true; } -void DSManagerForLayers::update_callbacks() +void DSForLayers::update_draw_scroll_line_cb() { - if (m_ticks.empty() || m_draw_mode == dmSequentialFffPrint) - imgui_ctrl.set_draw_scroll_line_cb(nullptr); + if (m_ticks.empty() || m_draw_mode == dmSequentialFffPrint || m_draw_mode == dmSlaPrint) + m_ctrl.set_draw_scroll_line_cb(nullptr); else - imgui_ctrl.set_draw_scroll_line_cb([this](const ImRect& scroll_line, const ImRect& slideable_region) { draw_colored_band(scroll_line, slideable_region); }); + m_ctrl.set_draw_scroll_line_cb([this](const ImRect& scroll_line, const ImRect& slideable_region) { draw_colored_band(scroll_line, slideable_region); }); } using namespace ImGui; -void DSManagerForLayers::draw_ticks(const ImRect& slideable_region) +void DSForLayers::draw_ticks(const ImRect& slideable_region) { //if(m_draw_mode != dmRegular) // return; @@ -231,7 +246,7 @@ void DSManagerForLayers::draw_ticks(const ImRect& slideable_region) const ImU32 tick_hovered_clr = ImGui::ColorConvertFloat4ToU32(ImGuiPureWrap::COL_WINDOW_BACKGROUND); auto get_tick_pos = [this, slideable_region](int tick) { - return imgui_ctrl.GetPositionFromValue(tick, slideable_region); + return m_ctrl.GetPositionInRect(tick, slideable_region); }; std::set::const_iterator tick_it = m_ticks.ticks.begin(); @@ -250,7 +265,7 @@ void DSManagerForLayers::draw_ticks(const ImRect& slideable_region) ++tick_it; } - auto active_tick_it = m_ticks.ticks.find(TickCode{ imgui_ctrl.GetActiveValue() }); + auto active_tick_it = m_ticks.ticks.find(TickCode{ m_ctrl.GetActivePos() }); tick_it = m_ticks.ticks.begin(); while (tick_it != m_ticks.ticks.end()) @@ -270,10 +285,10 @@ void DSManagerForLayers::draw_ticks(const ImRect& slideable_region) bool activate_this_tick = false; if (tick_it == active_tick_it && m_allow_editing) { // delete tick - if (render_button(ImGui::RemoveTick, ImGui::RemoveTickHovered, btn_label, icon_pos, imgui_ctrl.IsActiveHigherThumb() ? fiHigherThumb : fiLowerThumb, tick_it->tick)) { + if (render_button(ImGui::RemoveTick, ImGui::RemoveTickHovered, btn_label, icon_pos, m_ctrl.IsActiveHigherThumb() ? fiHigherThumb : fiLowerThumb, tick_it->tick)) { Type type = tick_it->type; m_ticks.ticks.erase(tick_it); - post_ticks_changed_event(type); + process_ticks_changed(); break; } } @@ -289,7 +304,7 @@ void DSManagerForLayers::draw_ticks(const ImRect& slideable_region) activate_this_tick = render_button(ImGui::EditGCode, ImGui::EditGCodeHovered, btn_label, icon_pos, fiActionIcon, tick_it->tick); if (activate_this_tick) { - imgui_ctrl.IsActiveHigherThumb() ? SetHigherValue(tick_it->tick) : SetLowerValue(tick_it->tick); + m_ctrl.IsActiveHigherThumb() ? SetHigherPos(tick_it->tick) : SetLowerPos(tick_it->tick); break; } @@ -318,7 +333,7 @@ static std::array decode_color_to_float_array(const std::string color) return ret; } -void DSManagerForLayers::draw_colored_band(const ImRect& groove, const ImRect& slideable_region) +void DSForLayers::draw_colored_band(const ImRect& groove, const ImRect& slideable_region) { if (m_ticks.empty() || m_draw_mode == dmSequentialFffPrint) return; @@ -352,7 +367,7 @@ void DSManagerForLayers::draw_colored_band(const ImRect& groove, const ImRect& s while (tick_it != m_ticks.ticks.end()) { //get position from tick - tick_pos = imgui_ctrl.GetPositionFromValue(tick_it->tick, slideable_region); + tick_pos = m_ctrl.GetPositionInRect(tick_it->tick, slideable_region); ImRect band_rect = ImRect(ImVec2(main_band.Min.x, std::min(tick_pos, main_band.Min.y)), ImVec2(main_band.Max.x, std::min(tick_pos, main_band.Max.y))); @@ -380,7 +395,7 @@ void DSManagerForLayers::draw_colored_band(const ImRect& groove, const ImRect& s } } -void DSManagerForLayers::render_menu() +void DSForLayers::render_menu() { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 10.0f) * m_scale); ImGui::PushStyleVar(ImGuiStyleVar_PopupRounding, 4.0f * m_scale); @@ -391,14 +406,14 @@ void DSManagerForLayers::render_menu() std::vector colors = wxGetApp().plater()->get_extruder_colors_from_plater_config(); int extruder_num = colors.size(); - if (imgui_ctrl.is_rclick_on_thumb()) { + if (m_ctrl.IsRClickOnThumb()) { ImGui::OpenPopup("slider_menu_popup"); } ImGui::PushStyleVar(ImGuiStyleVar_::ImGuiStyleVar_ChildRounding, 4.0f * m_scale); if (ImGui::BeginPopup("slider_menu_popup")) { - if ((!imgui_ctrl.IsActiveHigherThumb() && GetLowerValueD() == 0.0) || - (imgui_ctrl.IsActiveHigherThumb() && GetHigherValueD() == 0.0)) + if ((!m_ctrl.IsActiveHigherThumb() && GetLowerValue() == 0.0) || + (m_ctrl.IsActiveHigherThumb() && GetHigherValue() == 0.0)) { menu_item_with_icon(_u8L("Add Pause").c_str(), "", ImVec2(0, 0), 0, false, false); } @@ -442,7 +457,7 @@ void DSManagerForLayers::render_menu() ImGui::PopStyleVar(3); } -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*/) +bool DSForLayers::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; @@ -468,7 +483,7 @@ bool DSManagerForLayers::render_button(const wchar_t btn_icon, const wchar_t btn ImGuiContext& g = *GImGui; m_focus = focus; - std::string tooltip = m_allow_editing ? into_u8(get_tooltip(tick)) : ""; + std::string tooltip = m_allow_editing ? get_tooltip(tick) : ""; ImGui::SetCursorPos(ImVec2(0, 0)); const bool ret = m_imgui->image_button(g.HoveredWindow == g.CurrentWindow ? btn_icon_hovered : btn_icon, tooltip, false); @@ -480,25 +495,11 @@ bool DSManagerForLayers::render_button(const wchar_t btn_icon, const wchar_t btn return ret; } -void DSManagerForGcode::imgui_render(const int canvas_width, const int canvas_height, float extra_scale/* = 0.1f*/) +void DSForLayers::Render(const int canvas_width, const int canvas_height, float extra_scale/* = 0.1f*/) { - if (!imgui_ctrl.IsShown()) + if (!m_ctrl.IsShown()) return; - m_scale = extra_scale * 0.1f * wxGetApp().em_unit(); - - 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(); + m_scale = extra_scale * 0.1f * m_em; const float action_btn_sz = wxGetApp().imgui()->GetTextureCustomRect(ImGui::DSRevert)->Height; const float tick_icon_side = wxGetApp().imgui()->GetTextureCustomRect(ImGui::PausePrint)->Height; @@ -506,15 +507,15 @@ void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_h ImVec2 pos; ImVec2 size; - pos.x = canvas_width - VERTICAL_SLIDER_HEIGHT * m_scale - tick_icon_side; + pos.x = canvas_width - VERTICAL_SLIDER_WIDTH * 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); + size = ImVec2(VERTICAL_SLIDER_WIDTH * m_scale, canvas_height - 4.f * action_btn_sz); + m_ctrl.ShowLabelOnMouseMove(true); - imgui_ctrl.Init(pos, size, m_scale); - if (imgui_ctrl.render()) { + m_ctrl.Init(pos, size, m_scale); + if (m_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(); @@ -523,7 +524,7 @@ void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_h // draw action buttons - const float groove_center_x = imgui_ctrl.GetGrooveRect().GetCenter().x; + const float groove_center_x = m_ctrl.GetGrooveRect().GetCenter().x; ImVec2 btn_pos = ImVec2(groove_center_x - 0.5f * action_btn_sz, pos.y - 0.25f * action_btn_sz); @@ -532,7 +533,7 @@ void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_h discard_all_thicks(); btn_pos.y += 0.1f * action_btn_sz + size.y; - const bool is_one_layer = imgui_ctrl.IsCombineThumbs(); + const bool is_one_layer = m_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(); @@ -540,7 +541,7 @@ void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_h 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()) { + if (m_draw_mode == dmSequentialFffPrint && m_ctrl.IsRClickOnThumb()) { 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); @@ -549,7 +550,7 @@ void DSManagerForLayers::imgui_render(const int canvas_width, const int canvas_h render_menu(); } -bool DSManagerForLayers::is_wipe_tower_layer(int tick) const +bool DSForLayers::is_wipe_tower_layer(int tick) const { if (!m_is_wipe_tower || tick >= (int)m_values.size()) return false; @@ -603,7 +604,7 @@ static std::string short_and_splitted_time(const std::string& time) return get_s(); } -std::string DSManagerForLayers::get_label(int pos, LabelType label_type/* = ltHeightWithLayer*/) const +std::string DSForLayers::get_label(int pos, LabelType label_type/* = ltHeightWithLayer*/) const { const size_t value = pos; @@ -651,7 +652,7 @@ std::string DSManagerForLayers::get_label(int pos, LabelType label_type/* = ltHe return ""; } -std::string DSManagerForLayers::get_color_for_tool_change_tick(std::set::const_iterator it) const +std::string DSForLayers::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; @@ -665,7 +666,7 @@ std::string DSManagerForLayers::get_color_for_tool_change_tick(std::set::const_iterator it) const +std::string DSForLayers::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; @@ -687,48 +688,48 @@ std::string DSManagerForLayers::get_color_for_color_change_tick(std::set std::string { // when the tooltip is too long, it starts to flicker, see: https://github.com/prusa3d/PrusaSlicer/issues/7368 // so we limit the number of lines shown std::vector lines; @@ -782,50 +783,50 @@ wxString DSManagerForLayers::get_tooltip(int tick/*=-1*/) tooltip += tick_code_it->type == ColorChange ? (m_mode == SingleExtruder ? - format_wxstr(_L("Color change (\"%1%\")"), gcode(ColorChange)) : - format_wxstr(_L("Color change (\"%1%\") for Extruder %2%"), gcode(ColorChange), tick_code_it->extruder)) : + GUI::format(_L("Color change (\"%1%\")"), gcode(ColorChange)) : + GUI::format(_L("Color change (\"%1%\") for Extruder %2%"), gcode(ColorChange), tick_code_it->extruder)) : tick_code_it->type == PausePrint ? - format_wxstr(_L("Pause print (\"%1%\")"), gcode(PausePrint)) : + GUI::format(_L("Pause print (\"%1%\")"), gcode(PausePrint)) : tick_code_it->type == Template ? - format_wxstr(_L("Custom template (\"%1%\")"), gcode(Template)) : + GUI::format(_L("Custom template (\"%1%\")"), gcode(Template)) : tick_code_it->type == ToolChange ? - format_wxstr(_L("Extruder (tool) is changed to Extruder \"%1%\""), tick_code_it->extruder) : - from_u8(format_gcode(tick_code_it->extra));// tick_code_it->type == Custom + GUI::format(_L("Extruder (tool) is changed to Extruder \"%1%\""), tick_code_it->extruder) : + format_gcode(tick_code_it->extra);// tick_code_it->type == Custom // If tick is marked as a conflict (exclamation icon), // we should to explain why ConflictType conflict = m_ticks.is_conflict_tick(*tick_code_it, m_mode, m_only_extruder, m_values[tick]); if (conflict != ctNone) - tooltip += "\n\n" + _L("Note") + "! "; + tooltip += "\n\n" + _u8L("Note") + "! "; if (conflict == ctModeConflict) - tooltip += _L("G-code associated to this tick mark is in a conflict with print mode.\n" + tooltip += _u8L("G-code associated to this tick mark is in a conflict with print mode.\n" "Editing it will cause changes of Slider data."); else if (conflict == ctMeaninglessColorChange) - tooltip += _L("There is a color change for extruder that won't be used till the end of print job.\n" + tooltip += _u8L("There is a color change for extruder that won't be used till the end of print job.\n" "This code won't be processed during G-code generation."); else if (conflict == ctMeaninglessToolChange) - tooltip += _L("There is an extruder change set to the same extruder.\n" + tooltip += _u8L("There is an extruder change set to the same extruder.\n" "This code won't be processed during G-code generation."); else if (conflict == ctRedundant) - tooltip += _L("There is a color change for extruder that has not been used before.\n" + tooltip += _u8L("There is a color change for extruder that has not been used before.\n" "Check your settings to avoid redundant color changes."); // Show list of actions with existing tick if (m_focus == fiActionIcon) - tooltip += "\n\n" + _L("Delete tick mark - Left click or press \"-\" key") + "\n" + ( + tooltip += "\n\n" + _u8L("Delete tick mark - Left click or press \"-\" key") + "\n" + ( is_osx ? - _L("Edit tick mark - Ctrl + Left click") : - _L("Edit tick mark - Right click") ); + _u8L("Edit tick mark - Ctrl + Left click") : + _u8L("Edit tick mark - Right click") ); } - return tooltip; + return tooltip; } -void DSManagerForLayers::append_change_extruder_menu_item(wxMenu* menu, bool switch_current_code/* = false*/) +void DSForLayers::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) { - std::array active_extruders = get_active_extruders_for_tick(imgui_ctrl.GetActiveValue()); + std::array active_extruders = get_active_extruders_for_tick(m_ctrl.GetActivePos()); std::vector icons = get_extruder_color_icons(true); @@ -848,15 +849,15 @@ void DSManagerForLayers::append_change_extruder_menu_item(wxMenu* menu, bool swi append_submenu(menu, change_extruder_menu, wxID_ANY, change_extruder_menu_name, _L("Use another extruder"), active_extruders[1] > 0 ? "edit_uni" : "change_extruder", - [this]() {return m_mode == MultiAsSingle && !GUI::wxGetApp().obj_list()->has_paint_on_segmentation(); }, GUI::wxGetApp().plater()); + [this]() {return m_mode == MultiAsSingle /*&& !GUI::wxGetApp().obj_list()->has_paint_on_segmentation()*/; }, GUI::wxGetApp().plater()); // !ysFIXME has_paint_on_segmentation } } -void DSManagerForLayers::append_add_color_change_menu_item(wxMenu* menu, bool switch_current_code/* = false*/) +void DSForLayers::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) { - int tick = imgui_ctrl.GetActiveValue(); + int tick = m_ctrl.GetActivePos(); std::set used_extruders_for_tick = m_ticks.get_used_extruders_for_tick(tick, m_only_extruder, m_values[tick]); wxMenu* add_color_change_menu = new wxMenu(); @@ -880,7 +881,7 @@ void DSManagerForLayers::append_add_color_change_menu_item(wxMenu* menu, bool sw } } -void DSManagerForLayers::UseDefaultColors(bool def_colors_on) +void DSForLayers::UseDefaultColors(bool def_colors_on) { m_ticks.set_default_colors(def_colors_on); } @@ -889,7 +890,7 @@ void DSManagerForLayers::UseDefaultColors(bool def_colors_on) // 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 DSManagerForLayers::get_active_extruders_for_tick(int tick) const +std::array DSForLayers::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 }; @@ -912,73 +913,14 @@ std::array DSManagerForLayers::get_active_extruders_for_tick(int tick) c return extruders; } -// Get used extruders for tick. -// Means all extruders(tools) which will be used during printing from current tick to the end -std::set TickCodeInfo::get_used_extruders_for_tick(int tick, int only_extruder, double print_z, Mode force_mode/* = Undef*/) const -{ - Mode e_mode = !force_mode ? mode : force_mode; - - if (e_mode == MultiExtruder) { - // #ys_FIXME: get tool ordering from _correct_ place - const ToolOrdering& tool_ordering = 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(), print_z, [](const LayerTools &lhs, double rhs){ return lhs.print_z < rhs; }); - 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 = e_mode == MultiAsSingle ? std::max(only_extruder, 1) : 1; - if (ticks.empty() || e_mode == SingleExtruder) - return {default_initial_extruder}; - - std::set used_extruders; - - auto it_start = ticks.lower_bound(TickCode{tick}); - auto it = it_start; - if (it == ticks.begin() && it->type == ToolChange && - tick != it->tick ) // In case of switch of ToolChange to ColorChange, when tick exists, - // we shouldn't change color for extruder, which will be deleted - { - used_extruders.emplace(it->extruder); - if (tick < it->tick) - used_extruders.emplace(default_initial_extruder); - } - - while (it != ticks.begin()) { - --it; - if (it->type == ToolChange && tick != it->tick) { - used_extruders.emplace(it->extruder); - break; - } - } - - if (it == ticks.begin() && used_extruders.empty()) - used_extruders.emplace(default_initial_extruder); - - for (it = it_start; it != ticks.end(); ++it) - if (it->type == ToolChange && tick != it->tick) - used_extruders.emplace(it->extruder); - - return used_extruders; -} - -void DSManagerForLayers::show_cog_icon_context_menu() +void DSForLayers::show_cog_icon_context_menu() { wxMenu menu; append_menu_item(&menu, wxID_ANY, _L("Jump to height") + " (Shift+G)", "", [this](wxCommandEvent&) { jump_to_value(); }, "", & menu); + if (m_allow_editing) append_menu_check_item(&menu, wxID_ANY, _L("Use default colors"), _L("Use default colors on color change"), [this](wxCommandEvent&) { UseDefaultColors(!m_ticks.used_default_colors()); }, &menu, @@ -1025,7 +967,7 @@ bool check_color_change(const PrintObject* object, size_t frst_layer_id, size_t return detected; } -void DSManagerForLayers::auto_color_change() +void DSForLayers::auto_color_change() { if (!m_ticks.empty()) { wxString msg_text = _L("This action will cause deletion of all ticks on vertical slider.") + "\n\n" + @@ -1072,9 +1014,9 @@ void DSManagerForLayers::auto_color_change() if (m_ticks.empty()) GUI::wxGetApp().plater()->get_notification_manager()->push_notification(GUI::NotificationType::EmptyAutoColorChange); - update_callbacks(); + update_draw_scroll_line_cb(); - post_ticks_changed_event(); + process_ticks_changed(); } static std::string get_new_color(const std::string& color) @@ -1149,7 +1091,7 @@ static std::string get_custom_code(const std::string& code_in, double height) return ""; value = into_u8(dlg.GetValue()); - valid = GUI::Tab::validate_custom_gcode("Custom G-code", value); + valid = true;// GUI::Tab::validate_custom_gcode("Custom G-code", value); // !ysFIXME validate_custom_gcode } while (!valid); return value; } @@ -1170,11 +1112,12 @@ static std::string get_pause_print_msg(const std::string& msg_in, double height) return into_u8(dlg.GetValue()); } +// draw with imgui static double get_value_to_jump(double active_value, double min_z, double max_z, DrawMode mode) { 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); + wxString msg_in = "";// GUI::double_to_string(active_value); // get custom gcode wxTextEntryDialog dlg(nullptr, msg_text, msg_header, msg_in, wxTextEntryDialogStyle); @@ -1187,9 +1130,9 @@ static double get_value_to_jump(double active_value, double min_z, double max_z, return dlg.GetValue().ToDouble(&value) ? value : -1.0; } -void DSManagerForLayers::add_code_as_tick(Type type, int selected_extruder/* = -1*/) +void DSForLayers::add_code_as_tick(Type type, int selected_extruder/* = -1*/) { - const int tick = imgui_ctrl.GetActiveValue(); + const int tick = m_ctrl.GetActivePos(); if ( !check_ticks_changed_event(type) ) return; @@ -1216,14 +1159,17 @@ void DSManagerForLayers::add_code_as_tick(Type type, int selected_extruder/* = - return; if (was_ticks != m_ticks.empty()) - update_callbacks(); + update_draw_scroll_line_cb(); - post_ticks_changed_event(type); + process_ticks_changed(); } -void DSManagerForLayers::add_current_tick(bool call_from_keyboard /*= false*/) +void DSForLayers::add_current_tick() { - const int tick = imgui_ctrl.GetActiveValue(); + if (!m_allow_editing) + return; + + const int tick = m_ctrl.GetActivePos(); auto it = m_ticks.ticks.find(TickCode{ tick }); if (it != m_ticks.ticks.end() || // this tick is already exist @@ -1232,8 +1178,9 @@ void DSManagerForLayers::add_current_tick(bool call_from_keyboard /*= false*/) if (m_mode == SingleExtruder) add_code_as_tick(ColorChange); - /* else + render_menu(); + /* { wxMenu menu; @@ -1263,43 +1210,42 @@ void DSManagerForLayers::add_current_tick(bool call_from_keyboard /*= false*/) */ } -void DSManagerForLayers::delete_current_tick() +void DSForLayers::delete_current_tick() { - auto it = m_ticks.ticks.find(TickCode{ imgui_ctrl.GetActiveValue()}); + auto it = m_ticks.ticks.find(TickCode{ m_ctrl.GetActivePos()}); if (it == m_ticks.ticks.end() || !check_ticks_changed_event(it->type)) return; Type type = it->type; m_ticks.ticks.erase(it); - post_ticks_changed_event(type); + process_ticks_changed(); } -void DSManagerForLayers::edit_tick(int tick/* = -1*/) +void DSForLayers::edit_tick(int tick/* = -1*/) { if (tick < 0) - tick = imgui_ctrl.GetActiveValue(); + tick = m_ctrl.GetActivePos(); const std::set::iterator it = m_ticks.ticks.find(TickCode{ tick }); if (it == m_ticks.ticks.end() || !check_ticks_changed_event(it->type)) return; - Type type = it->type; if (m_ticks.edit_tick(it, m_values[it->tick])) - post_ticks_changed_event(type); + process_ticks_changed(); } // discard all custom changes on DoubleSlider -void DSManagerForLayers::discard_all_thicks() +void DSForLayers::discard_all_thicks() { m_ticks.ticks.clear(); - imgui_ctrl.ResetValues(); - update_callbacks(); - post_ticks_changed_event(); + m_ctrl.ResetPositions(); + update_draw_scroll_line_cb(); + process_ticks_changed(); } -void DSManagerForLayers::edit_extruder_sequence() +void DSForLayers::edit_extruder_sequence() { if (!check_ticks_changed_event(ToolChange)) return; @@ -1323,7 +1269,7 @@ void DSManagerForLayers::edit_extruder_sequence() std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd() std::uniform_int_distribution<> distrib(0, extr_cnt-1); - while (tick <= imgui_ctrl.GetMaxValue()) + while (tick <= m_ctrl.GetMaxPos()) { bool color_repetition = false; if (m_extruders_sequence.random_sequence) { @@ -1357,31 +1303,25 @@ void DSManagerForLayers::edit_extruder_sequence() tick += m_extruders_sequence.interval_by_layers; } - post_ticks_changed_event(ToolChange); + process_ticks_changed(); } -void DSManagerForLayers::jump_to_value() +void DSForLayers::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); + double value = get_value_to_jump(m_values[m_ctrl.GetActivePos()], + m_values[m_ctrl.GetMinPos()], m_values[m_ctrl.GetMaxPos()], m_draw_mode); if (value < 0.0) return; int tick_value = get_tick_from_value(value); - if (imgui_ctrl.IsActiveHigherThumb()) - SetHigherValue(tick_value); + if (m_ctrl.IsActiveHigherThumb()) + SetHigherPos(tick_value); else - SetLowerValue(tick_value); + SetLowerPos(tick_value); } -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 - process_ticks_changed(); -} - -bool DSManagerForLayers::check_ticks_changed_event(Type type) +bool DSForLayers::check_ticks_changed_event(Type type) { if ( m_ticks.mode == m_mode || (type != ColorChange && type != ToolChange) || @@ -1406,7 +1346,7 @@ bool DSManagerForLayers::check_ticks_changed_event(Type type) 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); + process_ticks_changed(); } return false; } @@ -1427,11 +1367,11 @@ bool DSManagerForLayers::check_ticks_changed_event(Type type) const int answer = msg.ShowModal(); if (answer == wxID_YES) { m_ticks.erase_all_ticks_with_code(ToolChange); - post_ticks_changed_event(ToolChange); + process_ticks_changed(); } else if (m_mode == SingleExtruder && answer == wxID_NO) { m_ticks.switch_code(ToolChange, ColorChange); - post_ticks_changed_event(ColorChange); + process_ticks_changed(); } return false; } @@ -1439,23 +1379,67 @@ bool DSManagerForLayers::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) + + + +// Get used extruders for tick. +// Means all extruders(tools) which will be used during printing from current tick to the end +std::set TickCodeInfo::get_used_extruders_for_tick(int tick, int only_extruder, double print_z, Mode force_mode/* = Undef*/) const { -#ifdef __WXOSX__ - is_osx = true; -#endif //__WXOSX__ - Init(lowerValue, higherValue, minValue, maxValue, "layers_slider", false); + Mode e_mode = !force_mode ? mode : force_mode; - 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); }); + if (e_mode == MultiExtruder) { + // #ys_FIXME: get tool ordering from _correct_ place + const ToolOrdering& tool_ordering = GUI::wxGetApp().plater()->fff_print().get_tool_ordering(); - m_ticks.set_pause_print_msg(_u8L("Place bearings in slots and resume printing")); - m_ticks.set_extruder_colors(&m_extruder_colors); + if (tool_ordering.empty()) + return {}; + + std::set used_extruders; + + auto it_layer_tools = std::lower_bound(tool_ordering.begin(), tool_ordering.end(), print_z, [](const LayerTools& lhs, double rhs) { return lhs.print_z < rhs; }); + 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 = e_mode == MultiAsSingle ? std::max(only_extruder, 1) : 1; + if (ticks.empty() || e_mode == SingleExtruder) + return { default_initial_extruder }; + + std::set used_extruders; + + auto it_start = ticks.lower_bound(TickCode{ tick }); + auto it = it_start; + if (it == ticks.begin() && it->type == ToolChange && + tick != it->tick) // In case of switch of ToolChange to ColorChange, when tick exists, + // we shouldn't change color for extruder, which will be deleted + { + used_extruders.emplace(it->extruder); + if (tick < it->tick) + used_extruders.emplace(default_initial_extruder); + } + + while (it != ticks.begin()) { + --it; + if (it->type == ToolChange && tick != it->tick) { + used_extruders.emplace(it->extruder); + break; + } + } + + if (it == ticks.begin() && used_extruders.empty()) + used_extruders.emplace(default_initial_extruder); + + for (it = it_start; it != ticks.end(); ++it) + if (it->type == ToolChange && tick != it->tick) + used_extruders.emplace(it->extruder); + + return used_extruders; } std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int extruder) diff --git a/src/slic3r/GUI/DoubleSlider.hpp b/src/slic3r/GUI/DoubleSliderForLayers.hpp similarity index 51% rename from src/slic3r/GUI/DoubleSlider.hpp rename to src/slic3r/GUI/DoubleSliderForLayers.hpp index 5a4c08d701..e486371f6a 100644 --- a/src/slic3r/GUI/DoubleSlider.hpp +++ b/src/slic3r/GUI/DoubleSliderForLayers.hpp @@ -2,8 +2,8 @@ ///|/ ///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher ///|/ -#ifndef slic3r_GUI_DoubleSlider_hpp_ -#define slic3r_GUI_DoubleSlider_hpp_ +#ifndef slic3r_GUI_DoubleSliderForLayers_hpp_ +#define slic3r_GUI_DoubleSliderForLayers_hpp_ #include "libslic3r/CustomGCode.hpp" #include "ImGuiDoubleSlider.hpp" @@ -23,11 +23,6 @@ namespace DoubleSlider { using namespace GUI; -/* For exporting GCode in GCodeWriter is used XYZF_NUM(val) = PRECISION(val, 3) for XYZ values. - * So, let use same value as a permissible error for layer height. - */ -constexpr double epsilon() { return 0.0011; } - // return true when areas are mostly equivalent bool equivalent_areas(const double& bottom_area, const double& top_area); @@ -60,20 +55,6 @@ enum ConflictType ctRedundant }; -enum MouseAction -{ - maNone, - maAddMenu, // show "Add" context menu for NOTexist active tick - maEditMenu, // show "Edit" context menu for exist active tick - maCogIconMenu, // show context for "cog" icon - maForceColorEdit, // force color editing from colored band - maAddTick, // force tick adding - maDeleteTick, // force tick deleting - maCogIconClick, // LeftMouseClick on "cog" icon - maOneLayerIconClick, // LeftMouseClick on "one_layer" icon - maRevertIconClick, // LeftMouseClick on "revert" icon -}; - enum DrawMode { dmRegular, @@ -192,148 +173,17 @@ struct ExtrudersSequence } }; -template -class DSManager_t + +class DSForLayers : public Manager { public: - - void Init( int lowerValue, + DSForLayers() : Manager() {} + DSForLayers(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(); } - int GetLowerValue() const { return imgui_ctrl.GetLowerValue(); } - int GetHigherValue()const { return imgui_ctrl.GetHigherValue(); } - - 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) { - 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 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 Show(bool show = true) { imgui_ctrl.Show(show); } - void Hide() { 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() {} + bool allow_editing); + ~DSForLayers() {} void ChangeOneLayerLock(); @@ -349,35 +199,38 @@ public: 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 "+" - void add_current_tick(bool call_from_keyboard = false); - // delete current tick, when press "-" - void delete_current_tick(); - void edit_tick(int tick = -1); - void discard_all_thicks(); - void edit_extruder_sequence(); - 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 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; - + void UseDefaultColors(bool def_colors_on); bool IsNewPrint(const std::string& print_obj_idxs); + void Render(const int canvas_width, const int canvas_height, float extra_scale = 1.f) override; + + void set_callback_on_ticks_changed(std::function cb) { m_cb_ticks_changed = cb; }; + + // manipulation with slider from keyboard + + // add default action for tick, when press "+" + void add_current_tick(); + // delete current tick, when press "-" + void delete_current_tick(); + // process adding of auto color change + void auto_color_change(); + // jump to selected layer + void jump_to_value(); + private: + void add_code_as_tick(Type type, int selected_extruder = -1); + void edit_tick(int tick = -1); + void discard_all_thicks(); + void edit_extruder_sequence(); + void show_cog_icon_context_menu(); + bool is_wipe_tower_layer(int tick) const; - std::string get_label(int tick, LabelType label_type = ltHeightWithLayer) const; + std::string get_label(int tick, LabelType label_type = ltHeightWithLayer) const; int get_tick_from_value(double value, bool force_lower_bound = false); - wxString get_tooltip(int tick = -1); + std::string 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; @@ -393,48 +246,44 @@ private: // Use those values to disable selection of active extruders std::array get_active_extruders_for_tick(int tick) const; - 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_add_color_change_menu_item(wxMenu*, bool switch_current_code = false); + void append_change_extruder_menu_item(wxMenu*, bool switch_current_code = false); // ysFIXME ! + void append_add_color_change_menu_item(wxMenu*, bool switch_current_code = false); // ysFIXME ! - bool is_osx{ false }; - bool m_allow_editing{ true }; + bool is_osx { false }; + bool m_allow_editing { true }; + bool m_is_wipe_tower { false }; //This flag indicates that there is multiple extruder print with wipe tower + bool m_show_estimated_times { false }; - 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 }; + Mode m_mode { SingleExtruder }; + FocusedItem m_focus { fiNone }; - DrawMode m_draw_mode { dmRegular }; - - Mode m_mode = SingleExtruder; - int m_only_extruder = -1; - - MouseAction m_mouse = maNone; - FocusedItem m_focus = fiNone; - - bool m_show_estimated_times{ false }; - - TickCodeInfo m_ticks; - std::vector m_layers_times; - std::vector m_layers_values; - std::vector m_extruder_colors; - - ExtrudersSequence m_extruders_sequence; - - std::function m_cb_ticks_changed{ nullptr }; + int m_only_extruder { -1 }; std::string m_print_obj_idxs; - // ImGuiDS + std::vector m_layers_times; + std::vector m_layers_values; + std::vector m_extruder_colors; + + TickCodeInfo m_ticks; + + ExtrudersSequence m_extruders_sequence; + + std::function m_cb_ticks_changed{ nullptr }; + bool m_can_change_color{ true }; + // functions for extend rendering of m_ctrl + void draw_colored_band(const ImRect& groove, const ImRect& slideable_region); void draw_ticks(const ImRect& slideable_region); 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(); + + void update_draw_scroll_line_cb(); }; } // DoubleSlider; @@ -443,4 +292,4 @@ private: -#endif // slic3r_GUI_DoubleSlider_hpp_ +#endif // slic3r_GUI_DoubleSliderForLayers_hpp_ diff --git a/src/slic3r/GUI/ExtruderSequenceDialog.hpp b/src/slic3r/GUI/ExtruderSequenceDialog.hpp index 37046834af..ab523c78c0 100644 --- a/src/slic3r/GUI/ExtruderSequenceDialog.hpp +++ b/src/slic3r/GUI/ExtruderSequenceDialog.hpp @@ -6,7 +6,7 @@ #define slic3r_GUI_ExtruderSequenceDialog_hpp_ #include "GUI_Utils.hpp" -#include "DoubleSlider.hpp" +#include "DoubleSliderForLayers.hpp" #include "wxExtensions.hpp" class wxTextCtrl; diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 1ada6188c7..d6188f3d92 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -14,6 +14,7 @@ #include "libslic3r/Utils.hpp" #include "libslic3r/LocalesUtils.hpp" #include "libslic3r/PresetBundle.hpp" +#include "libslic3r/CustomGCode.hpp" #include "slic3r/GUI/format.hpp" @@ -24,7 +25,6 @@ #include "I18N.hpp" #include "GUI_Utils.hpp" #include "GUI.hpp" -#include "DoubleSlider.hpp" #include "GLCanvas3D.hpp" #include "GLToolbar.hpp" #include "GUI_Preview.hpp" @@ -2120,12 +2120,12 @@ void GCodeViewer::render_legend(float& legend_height) if (extruder_id + 1 != static_cast(item.extruder)) continue; - if (item.type != ColorChange) + if (item.type != CustomGCode::ColorChange) continue; const std::vector zs = m_viewer.get_layers_zs(); auto lower_b = std::lower_bound(zs.begin(), zs.end(), - static_cast(item.print_z - Slic3r::DoubleSlider::epsilon())); + static_cast(item.print_z - Slic3r::CustomGCode::epsilon())); if (lower_b == zs.end()) continue; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index e3a9aadfef..07d2717c6a 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -19,7 +19,8 @@ #include "OpenGLManager.hpp" #include "GLCanvas3D.hpp" #include "libslic3r/PresetBundle.hpp" -#include "DoubleSlider.hpp" +#include "DoubleSliderForGcode.hpp" +#include "DoubleSliderForLayers.hpp" #include "Plater.hpp" #include "MainFrame.hpp" #include "format.hpp" @@ -197,8 +198,8 @@ Preview::Preview( void Preview::set_layers_slider_values_range(int bottom, int top) { - m_layers_slider->SetHigherValue(std::min(top, m_layers_slider->GetMaxValue())); - m_layers_slider->SetLowerValue(std::max(bottom, m_layers_slider->GetMinValue())); + m_layers_slider->SetHigherPos(std::min(top, m_layers_slider->GetMaxPos())); + m_layers_slider->SetLowerPos(std::max(bottom, m_layers_slider->GetMinPos())); } bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model) @@ -314,6 +315,8 @@ void Preview::reload_print() void Preview::msw_rescale() { + m_layers_slider->SetEmUnit(wxGetApp().em_unit()); + m_moves_slider->SetEmUnit(wxGetApp().em_unit()); // rescale warning legend on the canvas get_canvas3d()->msw_rescale(); @@ -328,9 +331,9 @@ void Preview::render_sliders(GLCanvas3D& canvas, float extra_scale/* = 0.1f*/) const int canvas_height = cnv_size.get_height(); if (m_layers_slider) - m_layers_slider->imgui_render(canvas_width, canvas_height, extra_scale); + m_layers_slider->Render(canvas_width, canvas_height, extra_scale); if (m_moves_slider) - m_moves_slider->imgui_render(canvas_width, canvas_height, extra_scale); + m_moves_slider->Render(canvas_width, canvas_height, extra_scale); } void Preview::bind_event_handlers() @@ -358,13 +361,12 @@ void Preview::create_sliders() { // Layers Slider - m_layers_slider = new DoubleSlider::DSManagerForLayers(0, 0, 0, 100, wxGetApp().is_editor()); + m_layers_slider = new DoubleSlider::DSForLayers(0, 0, 0, 100, wxGetApp().is_editor()); + m_layers_slider->SetEmUnit(wxGetApp().em_unit()); 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")); - m_layers_slider->enable_action_icon(wxGetApp().is_editor()); - m_layers_slider->set_callback_on_thumb_move( [this]() -> void { Preview::on_layers_slider_scroll_changed(); } ); m_layers_slider->set_callback_on_ticks_changed( [this]() -> void { @@ -378,7 +380,8 @@ void Preview::create_sliders() // Move Gcode Slider - m_moves_slider = new DoubleSlider::DSManagerForGcode(0, 0, 0, 100); + m_moves_slider = new DoubleSlider::DSForGcode(0, 0, 0, 100); + m_moves_slider->SetEmUnit(wxGetApp().em_unit()); m_moves_slider->set_callback_on_thumb_move([this]() ->void { Preview::on_moves_slider_scroll_changed(); }); @@ -423,7 +426,7 @@ void Preview::check_layers_slider_values(std::vector& ticks_f ticks_from_model.erase(std::remove_if(ticks_from_model.begin(), ticks_from_model.end(), [layers_z](CustomGCode::Item val) { - auto it = std::lower_bound(layers_z.begin(), layers_z.end(), val.print_z - DoubleSlider::epsilon()); + auto it = std::lower_bound(layers_z.begin(), layers_z.end(), val.print_z - CustomGCode::epsilon()); return it == layers_z.end(); }), ticks_from_model.end()); @@ -434,17 +437,17 @@ void Preview::check_layers_slider_values(std::vector& ticks_f void Preview::update_layers_slider(const std::vector& layers_z, bool keep_z_range) { // Save the initial slider span. - double z_low = m_layers_slider->GetLowerValueD(); - double z_high = m_layers_slider->GetHigherValueD(); - bool was_empty = m_layers_slider->GetMaxValue() == 0; + double z_low = m_layers_slider->GetLowerValue(); + double z_high = m_layers_slider->GetHigherValue(); + bool was_empty = m_layers_slider->GetMaxPos() == 0; bool force_sliders_full_range = was_empty; if (!keep_z_range) { - bool span_changed = layers_z.empty() || std::abs(layers_z.back() - m_layers_slider->GetMaxValueD()) > DoubleSlider::epsilon()/*1e-6*/; + bool span_changed = layers_z.empty() || std::abs(layers_z.back() - m_layers_slider->GetMaxValue()) > CustomGCode::epsilon()/*1e-6*/; force_sliders_full_range |= span_changed; } - bool snap_to_min = force_sliders_full_range || m_layers_slider->is_lower_at_min(); - bool snap_to_max = force_sliders_full_range || m_layers_slider->is_higher_at_max(); + bool snap_to_min = force_sliders_full_range || m_layers_slider->IsLowerAtMin(); + bool snap_to_max = force_sliders_full_range || m_layers_slider->IsHigherAtMax(); // Detect and set manipulation mode for double slider update_layers_slider_mode(); @@ -462,19 +465,19 @@ void Preview::update_layers_slider(const std::vector& layers_z, bool kee //first of all update extruder colors to avoid crash, when we are switching printer preset from MM to SM m_layers_slider->SetExtruderColors(plater->get_extruder_colors_from_plater_config(wxGetApp().is_editor() ? nullptr : m_gcode_result)); m_layers_slider->SetSliderValues(layers_z); - assert(m_layers_slider->GetMinValue() == 0); - m_layers_slider->SetMaxValue(layers_z.empty() ? 0 : layers_z.size() - 1); + assert(m_layers_slider->GetMinPos() == 0); + m_layers_slider->SetMaxPos(layers_z.empty() ? 0 : layers_z.size() - 1); int idx_low = 0; - int idx_high = m_layers_slider->GetMaxValue(); + int idx_high = m_layers_slider->GetMaxPos(); if (!layers_z.empty()) { if (!snap_to_min) { - int idx_new = find_close_layer_idx(layers_z, z_low, DoubleSlider::epsilon()/*1e-6*/); + int idx_new = find_close_layer_idx(layers_z, z_low, CustomGCode::epsilon()/*1e-6*/); if (idx_new != -1) idx_low = idx_new; } if (!snap_to_max) { - int idx_new = find_close_layer_idx(layers_z, z_high, DoubleSlider::epsilon()/*1e-6*/); + int idx_new = find_close_layer_idx(layers_z, z_high, CustomGCode::epsilon()/*1e-6*/); if (idx_new != -1) idx_high = idx_new; } @@ -625,17 +628,19 @@ void Preview::update_layers_slider_mode() void Preview::reset_layers_slider() { - m_layers_slider->SetHigherValue(0); - m_layers_slider->SetLowerValue(0); + m_layers_slider->SetHigherPos(0); + m_layers_slider->SetLowerPos(0); } void Preview::update_sliders_from_canvas(wxKeyEvent& event) { 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 == '-') + const bool can_edit = wxGetApp().is_editor(); + + if (can_edit && (key == WXK_NUMPAD_ADD || key == '+')) + m_layers_slider->add_current_tick(); + else if (can_edit && (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(); @@ -662,12 +667,12 @@ void Preview::update_sliders_from_canvas(wxKeyEvent& event) } 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); + const int new_pos = key == 'W' ? m_layers_slider->GetHigherPos() + 1 : m_layers_slider->GetHigherPos() - 1; + m_layers_slider->SetHigherPos(new_pos); } else if (key == 'A' || key == 'D') { - const int new_pos = key == 'D' ? m_moves_slider->GetHigherValue() + 1 : m_moves_slider->GetHigherValue() - 1; - m_moves_slider->SetHigherValue(new_pos); + const int new_pos = key == 'D' ? m_moves_slider->GetHigherPos() + 1 : m_moves_slider->GetHigherPos() - 1; + m_moves_slider->SetHigherPos(new_pos); } else if (key == 'X') m_layers_slider->ChangeOneLayerLock(); @@ -726,8 +731,10 @@ void Preview::update_moves_slider(std::optional visible_range_min, std::opt m_moves_slider->SetSliderValues(values); m_moves_slider->SetSliderAlternateValues(alternate_values); - m_moves_slider->SetMaxValue(static_cast(values.size()) - 1); + m_moves_slider->SetMaxPos(static_cast(values.size()) - 1); m_moves_slider->SetSelectionSpan(span_min_id, span_max_id); + + m_moves_slider->ShowLowerThumb(get_app_config()->get("seq_top_layer_only") == "0"); } void Preview::enable_moves_slider(bool enable) @@ -888,13 +895,13 @@ void Preview::on_layers_slider_scroll_changed() if (IsShown()) { PrinterTechnology tech = m_process->current_printer_technology(); if (tech == ptFFF) { - m_canvas->set_volumes_z_range({ m_layers_slider->GetLowerValueD(), m_layers_slider->GetHigherValueD() }); - m_canvas->set_toolpaths_z_range({ static_cast(m_layers_slider->GetLowerValue()), static_cast(m_layers_slider->GetHigherValue()) }); + m_canvas->set_volumes_z_range({ m_layers_slider->GetLowerValue(), m_layers_slider->GetHigherValue() }); + m_canvas->set_toolpaths_z_range({ static_cast(m_layers_slider->GetLowerPos()), static_cast(m_layers_slider->GetHigherPos()) }); m_canvas->set_as_dirty(); } else if (tech == ptSLA) { - m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_layers_slider->GetLowerValueD())); - m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_layers_slider->GetHigherValueD())); + m_canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -m_layers_slider->GetLowerValue())); + m_canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), m_layers_slider->GetHigherValue())); m_canvas->render(); } } @@ -902,7 +909,7 @@ void Preview::on_layers_slider_scroll_changed() 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->update_gcode_sequential_view_current(static_cast(m_moves_slider->GetLowerValue() - 1), static_cast(m_moves_slider->GetHigherValue() - 1)); m_canvas->set_as_dirty(); m_canvas->request_extra_frame(); } diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 452185fbe1..5118532965 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -28,8 +28,8 @@ class BackgroundSlicingProcess; class Model; namespace DoubleSlider { - class DSManagerForGcode; - class DSManagerForLayers; + class DSForGcode; + class DSForLayers; }; namespace GUI { @@ -96,8 +96,8 @@ class Preview : public wxPanel bool m_loaded { false }; - DoubleSlider::DSManagerForLayers* m_layers_slider{ nullptr }; - DoubleSlider::DSManagerForGcode* m_moves_slider { nullptr }; + DoubleSlider::DSForLayers* m_layers_slider{ nullptr }; + DoubleSlider::DSForGcode* m_moves_slider { nullptr }; public: enum class OptionType : unsigned int diff --git a/src/slic3r/GUI/ImGuiDoubleSlider.cpp b/src/slic3r/GUI/ImGuiDoubleSlider.cpp index 9befb33b87..a9e20a04c5 100644 --- a/src/slic3r/GUI/ImGuiDoubleSlider.cpp +++ b/src/slic3r/GUI/ImGuiDoubleSlider.cpp @@ -6,7 +6,9 @@ #include "ImGuiDoubleSlider.hpp" namespace Slic3r { -namespace GUI { +namespace DoubleSlider { + +using namespace GUI; const ImU32 tooltip_bg_clr = ImGui::ColorConvertFloat4ToU32(ImGuiPureWrap::COL_GREY_LIGHT); const ImU32 thumb_bg_clr = ImGui::ColorConvertFloat4ToU32(ImGuiPureWrap::COL_ORANGE_LIGHT); @@ -125,46 +127,47 @@ ImGuiControl::ImGuiControl( int lowerValue, bool use_lower_thumb) : m_selection(ssUndef), m_name(name), - m_lower_value(lowerValue), - m_higher_value (higherValue), - m_min_value(minValue), - m_max_value(maxValue), + m_lower_pos(lowerValue), + m_higher_pos (higherValue), + m_min_pos(minValue), + m_max_pos(maxValue), m_flags(flags), m_draw_lower_thumb(use_lower_thumb) { } -int ImGuiControl::GetActiveValue() const +int ImGuiControl::GetActivePos() const { - return m_selection == ssLower ? m_lower_value : - m_selection == ssHigher ? m_higher_value : -1; + return m_selection == ssLower ? m_lower_pos : + m_selection == ssHigher ? m_higher_pos : -1; } -void ImGuiControl::SetLowerValue(const int lower_val) +void ImGuiControl::SetLowerPos(const int lower_pos) { m_selection = ssLower; - m_lower_value = lower_val; - correct_lower_value(); + m_lower_pos = lower_pos; + correct_lower_pos(); } -void ImGuiControl::SetHigherValue(const int higher_val) +void ImGuiControl::SetHigherPos(const int higher_pos) { m_selection = ssHigher; - m_higher_value = higher_val; - correct_higher_value(); + m_higher_pos = higher_pos; + correct_higher_pos(); } -void ImGuiControl::SetSelectionSpan(const int lower_val, const int higher_val) +void ImGuiControl::SetSelectionSpan(const int lower_pos, const int higher_pos) { - m_lower_value = std::max(lower_val, m_min_value); - m_higher_value = std::max(std::min(higher_val, m_max_value), m_lower_value); - if (m_lower_value < m_higher_value) + m_lower_pos = std::max(lower_pos, m_min_pos); + m_higher_pos = std::max(std::min(higher_pos, m_max_pos), m_lower_pos); + if (m_lower_pos < m_higher_pos) m_combine_thumbs = false; } -void ImGuiControl::SetMaxValue(const int max_value) +void ImGuiControl::SetMaxPos(const int max_pos) { - m_max_value = max_value; + m_max_pos = max_pos; + correct_higher_pos(); } void ImGuiControl::MoveActiveThumb(int delta) @@ -173,36 +176,36 @@ void ImGuiControl::MoveActiveThumb(int delta) m_selection = ssHigher; if (m_selection == ssLower) { - m_lower_value -= delta; - correct_lower_value(); + m_lower_pos -= delta; + correct_lower_pos(); } else if (m_selection == ssHigher) { - m_higher_value -= delta; - correct_higher_value(); + m_higher_pos -= delta; + correct_higher_pos(); } } -void ImGuiControl::correct_lower_value() +void ImGuiControl::correct_lower_pos() { - if (m_lower_value < m_min_value) - m_lower_value = m_min_value; - else if (m_lower_value > m_max_value) - m_lower_value = m_max_value; + if (m_lower_pos < m_min_pos) + m_lower_pos = m_min_pos; + else if (m_lower_pos > m_max_pos) + m_lower_pos = m_max_pos; - if ((m_lower_value >= m_higher_value && m_lower_value <= m_max_value) || m_combine_thumbs) { - m_higher_value = m_lower_value; + if ((m_lower_pos >= m_higher_pos && m_lower_pos <= m_max_pos) || m_combine_thumbs) { + m_higher_pos = m_lower_pos; } } -void ImGuiControl::correct_higher_value() +void ImGuiControl::correct_higher_pos() { - if (m_higher_value > m_max_value) - m_higher_value = m_max_value; - else if (m_higher_value < m_min_value) - m_higher_value = m_min_value; + if (m_higher_pos > m_max_pos) + m_higher_pos = m_max_pos; + else if (m_higher_pos < m_min_pos) + m_higher_pos = m_min_pos; - if ((m_higher_value <= m_lower_value && m_higher_value >= m_min_value) || m_combine_thumbs) { - m_lower_value = m_higher_value; + if ((m_higher_pos <= m_lower_pos && m_higher_pos >= m_min_pos) || m_combine_thumbs) { + m_lower_pos = m_higher_pos; } } @@ -211,17 +214,17 @@ void ImGuiControl::CombineThumbs(bool combine) m_combine_thumbs = combine; if (combine) { m_selection = ssHigher; - correct_higher_value(); + correct_higher_pos(); } else - ResetValues(); + ResetPositions(); } -void ImGuiControl::ResetValues() +void ImGuiControl::ResetPositions() { - SetLowerValue(m_min_value); - SetHigherValue(m_max_value); - m_selection == ssLower ? correct_lower_value() : correct_higher_value(); + SetLowerPos(m_min_pos); + SetHigherPos(m_max_pos); + m_selection == ssLower ? correct_lower_pos() : correct_higher_pos(); } std::string ImGuiControl::get_label(int pos) const @@ -229,18 +232,18 @@ std::string ImGuiControl::get_label(int pos) const if (m_cb_get_label) return m_cb_get_label(pos); - if (pos >= m_max_value || pos < m_min_value) + if (pos >= m_max_pos || pos < m_min_pos) return "ErrVal"; return std::to_string(pos); } -float ImGuiControl::GetPositionFromValue(int value, const ImRect& rect) const +float ImGuiControl::GetPositionInRect(int pos, const ImRect& rect) const { - int v_min = m_min_value; - int v_max = m_max_value; + int v_min = m_min_pos; + int v_max = m_max_pos; - float pos_ratio = (v_max - v_min) != 0 ? ((float)(value - v_min) / (float)(v_max - v_min)) : 0.0f; + float pos_ratio = (v_max - v_min) != 0 ? ((float)(pos - v_min) / (float)(v_max - v_min)) : 0.0f; float thumb_pos; if (is_horizontal()) { thumb_pos = rect.Min.x + (rect.Max.x - rect.Min.x) * pos_ratio; @@ -324,7 +327,7 @@ void ImGuiControl::draw_thumb(const ImVec2& center, bool mark/* = false*/) } } -void ImGuiControl::apply_regions(int higher_value, int lower_value, const ImRect& draggable_region) +void ImGuiControl::apply_regions(int higher_pos, int lower_pos, const ImRect& draggable_region) { ImVec2 mid = draggable_region.GetCenter(); float thumb_radius = m_draw_opts.thumb_radius(); @@ -338,18 +341,18 @@ void ImGuiControl::apply_regions(int higher_value, int lower_value, const ImRect ImRect(draggable_region.Min + ImVec2(0, thumb_radius), draggable_region.Max); // initialize the thumbs. - float higher_thumb_pos = GetPositionFromValue(higher_value, m_regions.higher_slideable_region); + float higher_thumb_pos = GetPositionInRect(higher_pos, m_regions.higher_slideable_region); m_regions.higher_thumb = is_horizontal() ? ImRect(higher_thumb_pos - thumb_radius, mid.y - thumb_radius, higher_thumb_pos + thumb_radius, mid.y + thumb_radius) : ImRect(mid.x - thumb_radius, higher_thumb_pos - thumb_radius, mid.x + thumb_radius, higher_thumb_pos + thumb_radius); - float lower_thumb_pos = GetPositionFromValue(lower_value, m_regions.lower_slideable_region); + float lower_thumb_pos = GetPositionInRect(lower_pos, m_regions.lower_slideable_region); m_regions.lower_thumb = is_horizontal() ? ImRect(lower_thumb_pos - thumb_radius, mid.y - thumb_radius, lower_thumb_pos + thumb_radius, mid.y + thumb_radius) : ImRect(mid.x - thumb_radius, lower_thumb_pos - thumb_radius, mid.x + thumb_radius, lower_thumb_pos + thumb_radius); } -void ImGuiControl::check_and_correct_thumbs(int* higher_value, int* lower_value) +void ImGuiControl::check_and_correct_thumbs(int* higher_pos, int* lower_pos) { if (!m_draw_lower_thumb || m_combine_thumbs) return; @@ -366,12 +369,12 @@ void ImGuiControl::check_and_correct_thumbs(int* higher_value, int* lower_value) if (m_selection == ssHigher) { m_regions.lower_thumb = m_regions.higher_thumb; m_regions.higher_thumb.TranslateX(thumb_radius); - *lower_value = *higher_value; + *lower_pos = *higher_pos; } else { m_regions.higher_thumb = m_regions.lower_thumb; m_regions.lower_thumb.TranslateX(-thumb_radius); - *higher_value = *lower_value; + *higher_pos = *lower_pos; } } } @@ -380,18 +383,18 @@ void ImGuiControl::check_and_correct_thumbs(int* higher_value, int* lower_value) if (m_selection == ssHigher) { m_regions.lower_thumb = m_regions.higher_thumb; m_regions.lower_thumb.TranslateY(thumb_radius); - *lower_value = *higher_value; + *lower_pos = *higher_pos; } else { m_regions.higher_thumb = m_regions.lower_thumb; m_regions.lower_thumb.TranslateY(-thumb_radius); - *higher_value = *lower_value; + *higher_pos = *lower_pos; } } } } -bool ImGuiControl::draw_slider( int* higher_value, int* lower_value, +bool ImGuiControl::draw_slider( int* higher_pos, int* lower_pos, std::string& higher_label, std::string& lower_label, const ImVec2& pos, const ImVec2& size, float scale) { @@ -418,7 +421,7 @@ bool ImGuiControl::draw_slider( int* higher_value, int* lower_value, } // set slideable regions and thumbs. - apply_regions(*higher_value, *lower_value, draggable_region); + apply_regions(*higher_pos, *lower_pos, draggable_region); // select and mark higher thumb by default if (m_selection == ssUndef) @@ -433,28 +436,28 @@ bool ImGuiControl::draw_slider( int* higher_value, int* lower_value, ImGui::ItemHoverable(m_regions.lower_thumb, id) && context.IO.MouseClicked[0]) m_selection = ssLower; - // update thumb position and value - bool value_changed = false; + // update thumb position + bool pos_changed = false; if (m_selection == ssHigher) { - value_changed = behavior(id, m_regions.higher_slideable_region, m_min_value, m_max_value, - higher_value, &m_regions.higher_thumb, m_flags); + pos_changed = behavior(id, m_regions.higher_slideable_region, m_min_pos, m_max_pos, + higher_pos, &m_regions.higher_thumb, m_flags); } else if (m_draw_lower_thumb && !m_combine_thumbs) { - value_changed = behavior(id, m_regions.lower_slideable_region, m_min_value, m_max_value, - lower_value, &m_regions.lower_thumb, m_flags); + pos_changed = behavior(id, m_regions.lower_slideable_region, m_min_pos, m_max_pos, + lower_pos, &m_regions.lower_thumb, m_flags); } - // check thumbs values and correct them if needed - check_and_correct_thumbs(higher_value, lower_value); + // check thumbs poss and correct them if needed + check_and_correct_thumbs(higher_pos, lower_pos); const ImRect& slideable_region = m_selection == ssHigher ? m_regions.higher_slideable_region : m_regions.lower_slideable_region; const ImRect& active_thumb = m_selection == ssHigher ? m_regions.higher_thumb : m_regions.lower_thumb; bool show_move_label = false; ImRect mouse_pos_rc = active_thumb; - if (!value_changed && ImGui::ItemHoverable(item_size, id) && !ImGui::IsMouseDragging(0)) { - behavior(id, slideable_region, m_min_value, m_max_value, - &m_mouse_pos_value, &mouse_pos_rc, m_flags, true); + if (!pos_changed && ImGui::ItemHoverable(item_size, id) && !ImGui::IsMouseDragging(0)) { + behavior(id, slideable_region, m_min_pos, m_max_pos, + &m_mouse_pos, &mouse_pos_rc, m_flags, true); show_move_label = true; } @@ -491,9 +494,9 @@ bool ImGuiControl::draw_slider( int* higher_value, int* lower_value, // draw label on mouse move if (show_move_label) - draw_label(get_label_on_move(m_mouse_pos_value), mouse_pos_rc); + draw_label(get_label_on_move(m_mouse_pos), mouse_pos_rc); - return value_changed; + return pos_changed; } bool ImGuiControl::render() @@ -519,21 +522,21 @@ bool ImGuiControl::render() float scale = 1.f; - int higher_value = m_higher_value; - int lower_value = m_lower_value; - std::string higher_label = get_label(m_higher_value); - std::string lower_label = get_label(m_lower_value); - int temp_higher_value = m_higher_value; - int temp_lower_value = m_lower_value; + int higher_pos = m_higher_pos; + int lower_pos = m_lower_pos; + std::string higher_label = get_label(m_higher_pos); + std::string lower_label = get_label(m_lower_pos); + int temp_higher_pos = m_higher_pos; + int temp_lower_pos = m_lower_pos; - if (draw_slider(&higher_value, &lower_value, higher_label, lower_label, m_pos, m_size, scale)) { - if (temp_higher_value != higher_value) { - m_higher_value = higher_value; + if (draw_slider(&higher_pos, &lower_pos, higher_label, lower_label, m_pos, m_size, scale)) { + if (temp_higher_pos != higher_pos) { + m_higher_pos = higher_pos; if (m_combine_thumbs) - m_lower_value = m_higher_value; + m_lower_pos = m_higher_pos; } - if (temp_lower_value != lower_value) - m_lower_value = lower_value; + if (temp_lower_pos != lower_pos) + m_lower_pos = lower_pos; result = true; } diff --git a/src/slic3r/GUI/ImGuiDoubleSlider.hpp b/src/slic3r/GUI/ImGuiDoubleSlider.hpp index b2f2263707..b09f864acf 100644 --- a/src/slic3r/GUI/ImGuiDoubleSlider.hpp +++ b/src/slic3r/GUI/ImGuiDoubleSlider.hpp @@ -24,7 +24,7 @@ std::string to_string_with_precision(const T a_value, const int n = 2) } namespace Slic3r { -namespace GUI { +namespace DoubleSlider { enum SelectedSlider { ssUndef, @@ -45,25 +45,24 @@ public: ImGuiControl() {} ~ImGuiControl() {} - int GetMinValue() const { return m_min_value; } - int GetMaxValue() const { return m_max_value; } - int GetLowerValue() const { return m_lower_value; } - int GetHigherValue() const { return m_higher_value; } - int GetActiveValue() const; - float GetPositionFromValue(int value, const ImRect& rect) const; + int GetMinPos() const { return m_min_pos; } + int GetMaxPos() const { return m_max_pos; } + int GetLowerPos() const { return m_lower_pos; } + int GetHigherPos() const { return m_higher_pos; } + int GetActivePos() const; // 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 SetLowerPos (const int lower_pos); + void SetHigherPos(const int higher_pos); + void SetSelectionSpan(const int lower_pos, const int higher_pos); - void SetMaxValue(const int max_value); + void SetMaxPos(const int max_pos); void CombineThumbs(bool combine); - void ResetValues(); + void ResetPositions(); - void SetPos(ImVec2 pos) { m_pos = pos; } - void SetSize(ImVec2 size) { m_size = size; } - void SetScale(float scale) { m_draw_opts.scale = scale; } + void SetCtrlPos(ImVec2 pos) { m_pos = pos; } + void SetCtrlSize(ImVec2 size) { m_size = size; } + void SetCtrlScale(float scale) { m_draw_opts.scale = scale; } void Init(const ImVec2& pos, const ImVec2& size, float scale) { m_pos = pos; m_size = size; @@ -76,16 +75,15 @@ public: bool IsCombineThumbs() const { return m_combine_thumbs; } bool IsActiveHigherThumb() const { return m_selection == ssHigher; } void MoveActiveThumb(int delta); + void ShowLowerThumb(bool show) { m_draw_lower_thumb = show; } void ShowLabelOnMouseMove(bool show = true) { m_show_move_label = show; } ImRect GetGrooveRect() const { return m_draw_opts.groove(m_pos, m_size, is_horizontal()); } + float GetPositionInRect(int pos, const ImRect& rect) const; + + bool IsRClickOnThumb() const { return m_rclick_on_selected_thumb; } bool is_horizontal() const { return !(m_flags & ImGuiSliderFlags_Vertical); } - bool is_lower_at_min() const { return m_lower_value == m_min_value; } - bool is_higher_at_max() const { return m_higher_value == m_max_value; } - 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; } - bool render(); std::string get_label(int pos) const; @@ -130,11 +128,12 @@ 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_pos; + int m_max_pos; + int m_lower_pos; + int m_higher_pos; + // slider's position of the mouse cursor + int m_mouse_pos; bool m_rclick_on_selected_thumb{ false }; @@ -150,24 +149,136 @@ private: std::function m_cb_draw_scroll_line { nullptr }; std::function m_cb_extra_draw { nullptr }; - void correct_lower_value(); - void correct_higher_value(); + void correct_lower_pos(); + void correct_higher_pos(); 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 apply_regions(int higher_pos, int lower_pos, const ImRect& draggable_region); + void check_and_correct_thumbs(int* higher_pos, int* lower_pos); 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); - bool draw_slider(int* higher_value, int* lower_value, + bool draw_slider(int* higher_pos, int* lower_pos, std::string& higher_label, std::string& lower_label, const ImVec2& pos, const ImVec2& size, float scale = 1.0f); }; -} // GUI +// VatType = a typ of values, related to the each position in slider +template +class Manager +{ +public: + void Init( int lowerPos, + int higherPos, + int minPos, + int maxPos, + const std::string& name, + bool is_horizontal) + { + m_ctrl = ImGuiControl( lowerPos, higherPos, + minPos, maxPos, + is_horizontal ? 0 : ImGuiSliderFlags_Vertical, + name, !is_horizontal); + + m_ctrl.set_get_label_cb([this](int pos) {return get_label(pos); }); + }; + + Manager() {} + Manager(int lowerPos, + int higherPos, + int minPos, + int maxPos, + const std::string& name, + bool is_horizontal) + { + Init (lowerPos, higherPos, minPos, maxPos, name, is_horizontal); + } + ~Manager() {} + + int GetMinPos() const { return m_ctrl.GetMinPos(); } + int GetMaxPos() const { return m_ctrl.GetMaxPos(); } + int GetLowerPos() const { return m_ctrl.GetLowerPos(); } + int GetHigherPos()const { return m_ctrl.GetHigherPos(); } + + ValType GetMinValue() { return m_values.empty() ? static_cast(0) : m_values[GetMinPos()]; } + ValType GetMaxValue() { return m_values.empty() ? static_cast(0) : m_values[GetMaxPos()]; } + ValType GetLowerValue() { return m_values.empty() ? static_cast(0) : m_values[GetLowerPos()];} + ValType GetHigherValue() { return m_values.empty() ? static_cast(0) : m_values[GetHigherPos()]; } + + // Set low and high slider position. If the span is non-empty, disable the "one layer" mode. + void SetLowerPos(const int lower_pos) { + m_ctrl.SetLowerPos(lower_pos); + process_thumb_move(); + } + void SetHigherPos(const int higher_pos) { + m_ctrl.SetHigherPos(higher_pos); + process_thumb_move(); + } + void SetSelectionSpan(const int lower_pos, const int higher_pos) { + m_ctrl.SetSelectionSpan(lower_pos, higher_pos); + process_thumb_move(); + } + void SetMaxPos(const int max_pos) { + m_ctrl.SetMaxPos(max_pos); + process_thumb_move(); + } + + 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 IsLowerAtMin() const { return m_ctrl.GetLowerPos() == m_ctrl.GetMinPos(); } + bool IsHigherAtMax() const { return m_ctrl.GetHigherPos() == m_ctrl.GetMaxPos(); } + + void Show(bool show = true) { m_ctrl.Show(show); } + void Hide() { m_ctrl.Show(false); } + void SetEmUnit(int em_unit) { m_em = em_unit; } + void ShowLowerThumb(bool show) { m_ctrl.ShowLowerThumb(show); } + + virtual void 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) + { + m_ctrl.MoveActiveThumb(delta); + process_thumb_move(); + } + +protected: + + std::vector m_values; + std::vector m_alternate_values; + + ImGuiControl m_ctrl; + int m_em{ 10 }; + float m_scale{ 1.f }; + + std::string get_label(int pos) const { + if (m_values.empty()) + return std::to_string(pos); + if (pos >= m_values.size()) + return "ErrVal"; + return to_string_with_precision(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 }; + +}; + + + +} // GUI } // Slic3r