From 5632279213ebc851db7a40dba814172c2862baed Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 20 Dec 2018 10:55:50 +0100 Subject: [PATCH] Improvements of assigning the layer span to the layer slider on slice update. --- src/slic3r/GUI/GUI_Preview.cpp | 105 ++++++++++++++++++-------------- src/slic3r/GUI/GUI_Preview.hpp | 6 +- src/slic3r/GUI/wxExtensions.cpp | 15 +++++ src/slic3r/GUI/wxExtensions.hpp | 21 ++++--- 4 files changed, 88 insertions(+), 59 deletions(-) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 735b55125..579cd7e5e 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -214,7 +214,6 @@ Preview::Preview(wxNotebook* notebook, DynamicPrintConfig* config, BackgroundSli , m_preferred_color_mode("feature") , m_loaded(false) , m_enabled(false) - , m_force_sliders_full_range(false) , m_schedule_background_process(schedule_background_process_func) { #if ENABLE_REMOVE_TABS_FROM_PLATER @@ -514,14 +513,14 @@ void Preview::show_hide_ui_elements(const std::string& what) void Preview::reset_sliders() { m_enabled = false; - reset_double_slider(); +// reset_double_slider(); m_double_slider_sizer->Hide((size_t)0); } void Preview::update_sliders(const std::vector& layers_z) { m_enabled = true; - update_double_slider(layers_z, m_force_sliders_full_range); + update_double_slider(layers_z); m_double_slider_sizer->Show((size_t)0); Layout(); } @@ -597,26 +596,70 @@ void Preview::create_double_slider() }); } +// Find an index of a value in a sorted vector, which is in . +// Returns -1 if there is no such member. +static int find_close_layer_idx(const std::vector& zs, double &z, double eps) +{ + if (zs.empty()) + return -1; + auto it_h = std::lower_bound(zs.begin(), zs.end(), z); + if (it_h == zs.end()) { + auto it_l = it_h; + -- it_l; + if (z - *it_l < eps) + return int(zs.size() - 1); + } else if (it_h == zs.begin()) { + if (*it_h - z < eps) + return 0; + } else { + auto it_l = it_h; + -- it_l; + double dist_l = z - *it_l; + double dist_h = *it_h - z; + if (std::min(dist_l, dist_h) < eps) { + return (dist_l < dist_h) ? int(it_l - zs.begin()) : int(it_h - zs.begin()); + } + } + return -1; +} + void Preview::update_double_slider(const std::vector& layers_z, bool force_sliders_full_range) { + // Save the initial slider span. + double z_low = m_slider->GetLowerValueD(); + double z_high = m_slider->GetHigherValueD(); + bool was_empty = m_slider->GetMaxValue() == 0; + bool span_changed = layers_z.empty() || std::abs(layers_z.back() - m_slider->GetMaxValueD()) > 1e-6; + force_sliders_full_range |= was_empty | span_changed; + bool snap_to_min = force_sliders_full_range || m_slider->is_lower_at_min(); + bool snap_to_max = force_sliders_full_range || m_slider->is_higher_at_max(); + std::vector> values; fill_slider_values(values, layers_z); - - m_slider->SetMaxValue(layers_z.size() - 1); - if (force_sliders_full_range) - m_slider->SetHigherValue(layers_z.size() - 1); - m_slider->SetSliderValues(values); - const double z_low = m_slider->GetLowerValueD(); - const double z_high = m_slider->GetHigherValueD(); + assert(m_slider->GetMinValue() == 0); + m_slider->SetMaxValue(layers_z.empty() ? 0 : layers_z.size() - 1); + + int idx_low = 0; + int idx_high = m_slider->GetMaxValue(); + if (! layers_z.empty()) { + if (! snap_to_min) { + int idx_new = find_close_layer_idx(layers_z, z_low, 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, 1e-6); + if (idx_new != -1) + idx_high = idx_new; + } + } + m_slider->SetSelectionSpan(idx_low, idx_high); const auto& config = wxGetApp().preset_bundle->project_config; const std::vector &ticks_from_config = (config.option("colorprint_heights"))->values; - m_slider->SetTicksValues(ticks_from_config); - set_double_slider_thumbs(layers_z, z_low, z_high); - bool color_print_enable = (wxGetApp().plater()->printer_technology() == ptFFF); if (color_print_enable) { const auto& config = wxGetApp().preset_bundle->full_config(); @@ -638,8 +681,7 @@ void Preview::fill_slider_values(std::vector> &values, // All ticks that would end up outside the slider range should be erased. // TODO: this should be placed into more appropriate part of code, // this function is e.g. not called when the last object is deleted - auto& config = wxGetApp().preset_bundle->project_config; - std::vector &ticks_from_config = (config.option("colorprint_heights"))->values; + std::vector &ticks_from_config = (wxGetApp().preset_bundle->project_config.option("colorprint_heights"))->values; unsigned int old_size = ticks_from_config.size(); ticks_from_config.erase(std::remove_if(ticks_from_config.begin(), ticks_from_config.end(), [values](double val) { return values.back().second < val; }), @@ -648,32 +690,6 @@ void Preview::fill_slider_values(std::vector> &values, m_schedule_background_process(); } -void Preview::set_double_slider_thumbs(const std::vector &layers_z, - const double z_low, - const double z_high) -{ - // Force slider full range only when slider is created. - // Support selected diapason on the all next steps - if (z_high == 0.0) { - m_slider->SetLowerValue(0); - m_slider->SetHigherValue(layers_z.size() - 1); - return; - } - - for (int i = layers_z.size() - 1; i >= 0; i--) -// if (z_low >= layers_z[i]) { - if (fabs(z_low - layers_z[i]) <= 1e-6) { - m_slider->SetLowerValue(i); - break; - } - for (int i = layers_z.size() - 1; i >= 0; i--) -// if (z_high >= layers_z[i]) { - if (fabs(z_high-layers_z[i]) <= 1e-6) { - m_slider->SetHigherValue(i); - break; - } -} - void Preview::reset_double_slider() { m_slider->SetHigherValue(0); @@ -692,7 +708,7 @@ void Preview::update_double_slider_from_canvas(wxKeyEvent& event) if (key == 'U' || key == 'D') { const int new_pos = key == 'U' ? m_slider->GetHigherValue() + 1 : m_slider->GetHigherValue() - 1; m_slider->SetHigherValue(new_pos); - if (event.ShiftDown()) m_slider->SetLowerValue(m_slider->GetHigherValue()); + if (event.ShiftDown() || m_slider->is_one_layer()) m_slider->SetLowerValue(m_slider->GetHigherValue()); } else if (key == 'S') m_slider->ChangeOneLayerLock(); @@ -778,12 +794,8 @@ void Preview::load_print_as_fff() if (IsShown()) { - // used to set the sliders to the extremes of the current zs range - m_force_sliders_full_range = false; - if (gcode_preview_data_valid) { - m_force_sliders_full_range = (m_canvas->get_volumes_count() == 0); m_canvas->load_gcode_preview(*m_gcode_preview_data, colors); show_hide_ui_elements("full"); @@ -849,7 +861,6 @@ void Preview::load_print_as_sla() { std::vector layer_zs; std::copy(zs.begin(), zs.end(), std::back_inserter(layer_zs)); - m_force_sliders_full_range = true; update_sliders(layer_zs); } diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 534191633..bd71adcb5 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -117,7 +117,6 @@ class Preview : public wxPanel bool m_loaded; bool m_enabled; - bool m_force_sliders_full_range; PrusaDoubleSlider* m_slider {nullptr}; @@ -177,12 +176,9 @@ private: // Create/Update/Reset double slider on 3dPreview void create_double_slider(); - void update_double_slider(const std::vector& layers_z, bool force_sliders_full_range); + void update_double_slider(const std::vector& layers_z, bool force_sliders_full_range = false); void fill_slider_values(std::vector> &values, const std::vector &layers_z); - void set_double_slider_thumbs( const std::vector &layers_z, - const double z_low, - const double z_high); void reset_double_slider(); // update DoubleSlider after keyDown in canvas void update_double_slider_from_canvas(wxKeyEvent& event); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 2daba5df4..787c2a2a2 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -1506,6 +1506,21 @@ void PrusaDoubleSlider::SetHigherValue(const int higher_val) ProcessWindowEvent(e); } +void PrusaDoubleSlider::SetSelectionSpan(const int lower_val, const int higher_val) +{ + 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_is_one_layer = false; + + Refresh(); + Update(); + + wxCommandEvent e(wxEVT_SCROLL_CHANGED); + e.SetEventObject(this); + ProcessWindowEvent(e); +} + void PrusaDoubleSlider::SetMaxValue(const int max_value) { m_max_value = max_value; diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index e8fba1ea2..b951c5635 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -697,18 +697,20 @@ public: const wxString& name = wxEmptyString); ~PrusaDoubleSlider() {} - int GetLowerValue() const { - return m_lower_value; - } - int GetHigherValue() const { - return m_higher_value; - } + int GetMinValue() const { return m_min_value; } + int GetMaxValue() const { return m_max_value; } + double GetMinValueD() { return m_values.empty() ? 0. : m_values[m_min_value].second; } + double GetMaxValueD() { return m_values.empty() ? 0. : m_values[m_max_value].second; } + int GetLowerValue() const { return m_lower_value; } + int GetHigherValue() const { return m_higher_value; } int GetActiveValue() const; double GetLowerValueD() { return get_double_value(ssLower); } double GetHigherValueD() { return get_double_value(ssHigher); } wxSize DoGetBestSize() const override; void SetLowerValue(const int lower_val); void SetHigherValue(const int higher_val); + // Set low and high slider position. If the span is non-empty, disable the "one layer" mode. + void SetSelectionSpan(const int lower_val, const int higher_val); void SetMaxValue(const int max_value); void SetKoefForLabels(const double koef) { m_label_koef = koef; @@ -726,6 +728,12 @@ public: EnableTickManipulation(false); } + bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; } + bool is_one_layer() const { return m_is_one_layer; } + bool is_lower_at_min() const { return m_lower_value == m_min_value; } + 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(); } + void OnPaint(wxPaintEvent& ) { render();} void OnLeftDown(wxMouseEvent& event); void OnMotion(wxMouseEvent& event); @@ -762,7 +770,6 @@ protected: bool is_point_in_rect(const wxPoint& pt, const wxRect& rect); int is_point_near_tick(const wxPoint& pt); - bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; } double get_scroll_step(); wxString get_label(const SelectedSlider& selection) const;