diff --git a/lib/Slic3r/GUI/Plater/3DPreview.pm b/lib/Slic3r/GUI/Plater/3DPreview.pm index 09c2f0b8c..c2c5e08b4 100644 --- a/lib/Slic3r/GUI/Plater/3DPreview.pm +++ b/lib/Slic3r/GUI/Plater/3DPreview.pm @@ -10,7 +10,7 @@ use base qw(Wx::Panel Class::Accessor); use Wx::Locale gettext => 'L'; -__PACKAGE__->mk_accessors(qw(print gcode_preview_data enabled _loaded canvas slider_low slider_high single_layer)); +__PACKAGE__->mk_accessors(qw(print gcode_preview_data enabled _loaded canvas slider_low slider_high single_layer double_slider_sizer)); sub new { my $class = shift; @@ -102,6 +102,12 @@ sub new { .L("Wipe tower")."|" .L("Custom"); Slic3r::GUI::create_combochecklist($combochecklist_features, $feature_text, $feature_items, 1); + + # **************** EXP ****************** + my $double_slider_sizer = Wx::BoxSizer->new(wxHORIZONTAL); + Slic3r::GUI::create_double_slider($self, $double_slider_sizer, $self->canvas); + $self->double_slider_sizer($double_slider_sizer); + # **************** EXP ****************** my $checkbox_travel = $self->{checkbox_travel} = Wx::CheckBox->new($self, -1, L("Travel")); my $checkbox_retractions = $self->{checkbox_retractions} = Wx::CheckBox->new($self, -1, L("Retractions")); @@ -120,6 +126,9 @@ sub new { $vsizer->Add($z_label_high_idx, 0, wxALIGN_CENTER_HORIZONTAL, 0); $vsizer->Add($z_label_high, 0, 0, 0); $hsizer->Add($vsizer, 0, wxEXPAND, 0); + # **************** EXP ****************** + $hsizer->Add($double_slider_sizer, 0, wxEXPAND, 0); + # **************** EXP ****************** $vsizer_outer->Add($hsizer, 3, wxALIGN_CENTER_HORIZONTAL, 0); $vsizer_outer->Add($checkbox_singlelayer, 0, wxTOP | wxALIGN_CENTER_HORIZONTAL, 5); @@ -385,6 +394,7 @@ sub load_print { } $self->update_sliders($n_layers) if ($n_layers > 0); + Slic3r::GUI::update_double_slider($self->{force_sliders_full_range}) if ($n_layers > 0); $self->_loaded(1); } } @@ -399,6 +409,9 @@ sub reset_sliders { $self->{z_label_high}->SetLabel(""); $self->{z_label_low_idx}->SetLabel(""); $self->{z_label_high_idx}->SetLabel(""); + + Slic3r::GUI::reset_double_slider(); + $self->double_slider_sizer->Hide(0); } sub update_sliders @@ -448,6 +461,9 @@ sub update_sliders $self->slider_low->Show; $self->slider_high->Show; $self->set_z_range($self->{layers_z}[$z_idx_low], $self->{layers_z}[$z_idx_high]); + + $self->double_slider_sizer->Show(0); + $self->Layout; } diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 4592e6433..34865fa63 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -116,7 +116,6 @@ wxNotebook *g_wxTabPanel = nullptr; AppConfig *g_AppConfig = nullptr; PresetBundle *g_PresetBundle= nullptr; PresetUpdater *g_PresetUpdater = nullptr; -_3DScene *g_3DScene = nullptr; wxColour g_color_label_modified; wxColour g_color_label_sys; wxColour g_color_label_default; @@ -222,11 +221,6 @@ void set_preset_updater(PresetUpdater *updater) g_PresetUpdater = updater; } -void set_3DScene(_3DScene *scene) -{ - g_3DScene = scene; -} - void set_objects_from_perl( wxWindow* parent, wxBoxSizer *frequently_changed_parameters_sizer, wxBoxSizer *expert_mode_part_sizer, wxBoxSizer *scrolled_window_sizer, wxButton *btn_export_gcode, diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index 69e83eaab..22ea3edb0 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -35,7 +35,6 @@ class AppConfig; class PresetUpdater; class DynamicPrintConfig; class TabIface; -class _3DScene; #define _(s) Slic3r::GUI::I18N::translate((s)) @@ -101,7 +100,6 @@ void set_tab_panel(wxNotebook *tab_panel); void set_app_config(AppConfig *app_config); void set_preset_bundle(PresetBundle *preset_bundle); void set_preset_updater(PresetUpdater *updater); -void set_3DScene(_3DScene *scene); void set_objects_from_perl( wxWindow* parent, wxBoxSizer *frequently_changed_parameters_sizer, wxBoxSizer *expert_mode_part_sizer, diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp index 94555f50e..9b1214b38 100644 --- a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -13,6 +13,9 @@ #include "Geometry.hpp" #include "slic3r/Utils/FixModelByWin10.hpp" +#include +#include "3DScene.hpp" + namespace Slic3r { namespace GUI @@ -23,6 +26,8 @@ wxSizer *m_sizer_object_movers = nullptr; wxDataViewCtrl *m_objects_ctrl = nullptr; PrusaObjectDataViewModel *m_objects_model = nullptr; wxCollapsiblePane *m_collpane_settings = nullptr; +PrusaDoubleSlider *m_slider = nullptr; +wxGLCanvas *m_preview_canvas = nullptr; wxIcon m_icon_modifiermesh; wxIcon m_icon_solidmesh; @@ -1668,5 +1673,80 @@ void update_objects_list_extruder_column(int extruders_count) set_extruder_column_hidden(extruders_count <= 1); } +void create_double_slider(wxWindow* parent, wxBoxSizer* sizer, wxGLCanvas* canvas) +{ + m_slider = new PrusaDoubleSlider(parent, wxID_ANY, 0, 0, 0, 100); + sizer->Add(m_slider, 0, wxEXPAND, 0); + + m_preview_canvas = canvas; + + m_slider->Bind(wxEVT_SCROLL_CHANGED, [parent](wxEvent& event) { + _3DScene::set_toolpaths_range(m_preview_canvas, m_slider->GetLowerValueD() - 1e-6, m_slider->GetHigherValueD() + 1e-6); + if (parent->IsShown()) + m_preview_canvas->Refresh(); + }); +} + +void fill_slider_values(std::vector> &values, + const std::vector &layers_z) +{ + std::vector layers_all_z = _3DScene::get_current_print_zs(m_preview_canvas, false); + if (layers_all_z.size() == layers_z.size()) + for (int i = 0; i < layers_z.size(); i++) + values.push_back(std::pair(i+1, layers_z[i])); + else if (layers_all_z.size() > layers_z.size()) { + int cur_id = 0; + for (int i = 0; i < layers_z.size(); i++) + for (int j = cur_id; j < layers_all_z.size(); j++) + if (layers_z[i] - 1e-6 < layers_all_z[j] && layers_all_z[j] < layers_z[i] + 1e-6) { + values.push_back(std::pair(j+1, layers_z[i])); + cur_id = j; + break; + } + } +} + +void set_double_slider_thumbs( const bool force_sliders_full_range, + const std::vector &layers_z, + const double z_low, const double z_high) +{ + if (force_sliders_full_range) { + 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]) { + m_slider->SetLowerValue(i); + break; + } + for (int i = layers_z.size() - 1; i >= 0 ; i--) + if (z_high >= layers_z[i]) { + m_slider->SetHigherValue(i); + break; + } +} + +void update_double_slider(bool force_sliders_full_range) +{ + std::vector> values; + std::vector layers_z = _3DScene::get_current_print_zs(m_preview_canvas, true); + fill_slider_values(values, layers_z); + + const double z_low = m_slider->GetLowerValueD(); + const double z_high = m_slider->GetHigherValueD(); + m_slider->SetMaxValue(layers_z.size() - 1); + m_slider->SetSliderValues(values); + + set_double_slider_thumbs(force_sliders_full_range, layers_z, z_low, z_high); +} + +void reset_double_slider() +{ + m_slider->SetHigherValue(0); + m_slider->SetLowerValue(0); +} + } //namespace GUI } //namespace Slic3r \ No newline at end of file diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp index 82bfe4a6c..f659cf404 100644 --- a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp +++ b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp @@ -9,13 +9,14 @@ class wxArrayString; class wxMenu; class wxDataViewEvent; class wxKeyEvent; -class wxControl; +class wxGLCanvas; namespace Slic3r { class ModelObject; class Model; namespace GUI { +//class wxGLCanvas; enum ogGroup{ ogFrequentlyChangingParameters, @@ -69,8 +70,6 @@ void select_current_object(int idx); // Remove objects/sub-object from the list void remove(); -//void create_double_slider(wxWindow* parent, wxControl* slider); - void object_ctrl_selection_changed(); void object_ctrl_context_menu(); void object_ctrl_key_event(wxKeyEvent& event); @@ -123,6 +122,11 @@ void on_drop(wxDataViewEvent &event); // update extruder column for objects_ctrl according to extruders count void update_objects_list_extruder_column(int extruders_count); +// Create/Update/Reset double slider on 3dPreview +void create_double_slider(wxWindow* parent, wxBoxSizer* sizer, wxGLCanvas* canvas); +void update_double_slider(bool force_sliders_full_range); +void reset_double_slider(); + } //namespace GUI } //namespace Slic3r #endif //slic3r_GUI_ObjectParts_hpp_ \ No newline at end of file diff --git a/xs/src/slic3r/GUI/wxExtensions.cpp b/xs/src/slic3r/GUI/wxExtensions.cpp index e646ed0ec..685c4d8d0 100644 --- a/xs/src/slic3r/GUI/wxExtensions.cpp +++ b/xs/src/slic3r/GUI/wxExtensions.cpp @@ -832,6 +832,10 @@ void PrusaDoubleSlider::SetLowerValue(const int lower_val) m_lower_value = lower_val; Refresh(); Update(); + + wxCommandEvent e(wxEVT_SCROLL_CHANGED); + e.SetEventObject(this); + ProcessWindowEvent(e); } void PrusaDoubleSlider::SetHigherValue(const int higher_val) @@ -839,6 +843,10 @@ void PrusaDoubleSlider::SetHigherValue(const int higher_val) m_higher_value = higher_val; Refresh(); Update(); + + wxCommandEvent e(wxEVT_SCROLL_CHANGED); + e.SetEventObject(this); + ProcessWindowEvent(e); } void PrusaDoubleSlider::SetMaxValue(const int max_value) @@ -905,6 +913,13 @@ void PrusaDoubleSlider::get_size(int *w, int *h) is_horizontal() ? *w -= m_lock_icon_dim : *h -= m_lock_icon_dim; } +double PrusaDoubleSlider::get_double_value(const SelectedSlider& selection) const +{ + if (m_values.empty()) + return 0.0; + return m_values[selection == ssLower ? m_lower_value : m_higher_value].second; +} + void PrusaDoubleSlider::get_lower_and_higher_position(int& lower_pos, int& higher_pos) { const double step = get_scroll_step(); @@ -1245,6 +1260,10 @@ void PrusaDoubleSlider::OnMotion(wxMouseEvent& event) Refresh(); Update(); event.Skip(); + + wxCommandEvent e(wxEVT_SCROLL_CHANGED); + e.SetEventObject(this); + ProcessWindowEvent(e); } void PrusaDoubleSlider::OnLeftUp(wxMouseEvent& event) diff --git a/xs/src/slic3r/GUI/wxExtensions.hpp b/xs/src/slic3r/GUI/wxExtensions.hpp index 76e59f2eb..00973e74f 100644 --- a/xs/src/slic3r/GUI/wxExtensions.hpp +++ b/xs/src/slic3r/GUI/wxExtensions.hpp @@ -516,7 +516,7 @@ public: int maxValue, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, - long style = wxSL_HORIZONTAL, + long style = wxSL_VERTICAL, const wxValidator& val = wxDefaultValidator, const wxString& name = wxEmptyString); ~PrusaDoubleSlider(){} @@ -528,6 +528,8 @@ public: return m_higher_value; } int GetActiveValue() const; + double GetLowerValueD() const { return get_double_value(ssLower); } + double GetHigherValueD() const { return get_double_value(ssHigher); } wxSize DoGetBestSize() const override; void SetLowerValue(const int lower_val); void SetHigherValue(const int higher_val); @@ -583,6 +585,7 @@ protected: wxCoord get_position_from_value(const int value); wxSize get_size(); void get_size(int *w, int *h); + double get_double_value(const SelectedSlider& selection) const; private: int m_min_value; diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp index c18fce44d..3e967bb86 100644 --- a/xs/xsp/GUI.xsp +++ b/xs/xsp/GUI.xsp @@ -173,16 +173,21 @@ void desktop_open_datadir_folder() void fix_model_by_win10_sdk_gui(ModelObject *model_object_src, Print *print, Model *model_dst) %code%{ Slic3r::fix_model_by_win10_sdk_gui(*model_object_src, *print, *model_dst); %}; -void set_3DScene(SV *scene) - %code%{ Slic3r::GUI::set_3DScene((_3DScene *)wxPli_sv_2_object(aTHX_ scene, "Slic3r::Model::3DScene") ); %}; - void register_on_request_update_callback(SV* callback) %code%{ Slic3r::GUI::g_on_request_update_callback.register_callback(callback); %}; void deregister_on_request_update_callback() %code%{ Slic3r::GUI::g_on_request_update_callback.deregister_callback(); %}; -//void create_double_slider(SV *ui_parent, SV *ui_ds) -// %code%{ Slic3r::GUI::create_double_slider( (wxWindow*)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"), -// (wxControl*)wxPli_sv_2_object(aTHX_ ui_ds, "Wx::Control")); %}; +void create_double_slider(SV *ui_parent, SV *ui_sizer, SV *ui_canvas) + %code%{ Slic3r::GUI::create_double_slider( (wxWindow*)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"), + (wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer"), + (wxGLCanvas*)wxPli_sv_2_object(aTHX_ ui_canvas, "Wx::GLCanvas")); %}; + +void update_double_slider(bool force_sliders_full_range) + %code%{ Slic3r::GUI::update_double_slider(force_sliders_full_range); %}; + +void reset_double_slider() + %code%{ Slic3r::GUI::reset_double_slider(); %}; +