diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 8e5882049..eb95bc4d4 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -2236,7 +2236,7 @@ sub changed_object_settings { # recenter and re-align to Z = 0 my $model_object = $self->{model}->objects->[$obj_idx]; $model_object->center_around_origin; - $self->reset_thumbnail($obj_idx); +# $self->reset_thumbnail($obj_idx); } # update print diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 9e28de04a..ee12e0492 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -1126,6 +1126,13 @@ void show_info_sizer(bool show) g_manifold_warning_icon->Show(show && g_show_manifold_warning_icon); } +void show_object_name(bool show) +{ + wxGridSizer* grid_sizer = get_optgroup(ogFrequentlyObjectSettings)->get_grid_sizer(); + grid_sizer->Show(static_cast(0), show); + grid_sizer->Show(static_cast(1), show); +} + void update_mode() { wxWindowUpdateLocker noUpdates(g_right_panel); @@ -1145,6 +1152,7 @@ void update_mode() g_object_list_sizer->Show(mode == ConfigMenuModeExpert); show_info_sizer(mode == ConfigMenuModeExpert); show_buttons(mode == ConfigMenuModeExpert); + show_object_name(mode == ConfigMenuModeSimple); // TODO There is a not the best place of it! // *** Update showing of the collpane_settings diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp index 50b1a1f5a..f6d9ad3c2 100644 --- a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -43,8 +43,7 @@ bool g_prevent_list_events = false; // We use this flag to avoid circular even // happens to fire a wxEVT_LIST_ITEM_SELECTED on OSX, whose event handler // calls this method again and again and again bool g_is_percent_scale = false; // It indicates if scale unit is percentage -int g_rotation_x = 0; // Last value of the rotation around the X axis -int g_rotation_y = 0; // Last value of the rotation around the Y axis +bool g_is_uniform_scale = false; // It indicates if scale is uniform ModelObjectPtrs* m_objects; std::shared_ptr m_config; std::shared_ptr m_default_config; @@ -492,12 +491,21 @@ void add_objects_list(wxWindow* parent, wxBoxSizer* sizer) Line add_og_to_object_settings(const std::string& option_name, const std::string& sidetext, int def_value = 0) { Line line = { _(option_name), "" }; + if (option_name == "Scale") { + line.near_label_widget = [](wxWindow* parent) { + auto btn = new PrusaLockButton(parent, wxID_ANY); + btn->Bind(wxEVT_BUTTON, [btn](wxCommandEvent &event){ + event.Skip(); + wxTheApp->CallAfter([btn]() { set_uniform_scaling(btn->IsLocked()); }); + }); + return btn; + }; + } ConfigOptionDef def; def.type = coInt; def.default_value = new ConfigOptionInt(def_value); - def.sidetext = sidetext; - def.width = 70; + def.width = 55; if (option_name == "Rotation") def.min = -360; @@ -506,7 +514,8 @@ Line add_og_to_object_settings(const std::string& option_name, const std::string std::vector axes{ "x", "y", "z" }; for (auto axis : axes) { - def.label = boost::algorithm::to_upper_copy(axis); + if (axis == "z" && option_name != "Scale") + def.sidetext = sidetext; Option option = Option(def, lower_name + "_" + axis); option.opt.full_width = true; line.append_option(option); @@ -514,15 +523,14 @@ Line add_og_to_object_settings(const std::string& option_name, const std::string if (option_name == "Scale") { - def.label = L("Units"); - def.type = coStrings; + def.width = 45; + def.type = coStrings; def.gui_type = "select_open"; def.enum_labels.push_back(L("%")); def.enum_labels.push_back(L("mm")); - def.default_value = new ConfigOptionStrings{ "%" }; - def.sidetext = " "; + def.default_value = new ConfigOptionStrings{ "mm" }; - Option option = Option(def, lower_name + "_unit"); + const Option option = Option(def, lower_name + "_unit"); line.append_option(option); } @@ -549,15 +557,9 @@ void add_object_settings(wxWindow* parent, wxBoxSizer* sizer) } }; -// def.label = L("Name"); -// def.type = coString; -// def.tooltip = L("Object name"); -// def.full_width = true; -// def.default_value = new ConfigOptionString{ "BlaBla_object.stl" }; -// optgroup->append_single_option_line(Option(def, "object_name")); - ConfigOptionDef def; + // Objects(sub-objects) name def.label = L("Name"); // def.type = coString; def.gui_type = "legend"; @@ -566,14 +568,28 @@ void add_object_settings(wxWindow* parent, wxBoxSizer* sizer) def.default_value = new ConfigOptionString{ " " }; optgroup->append_single_option_line(Option(def, "object_name")); - optgroup->set_flag(ogSIDE_OPTIONS_VERTICAL); - optgroup->sidetext_width = 25; + // Legend for object modification + auto line = Line{ "", "" }; + def.label = ""; + def.type = coString; + def.width = 55; + + std::vector axes{ "x", "y", "z" }; + for (const auto axis : axes) { + const auto label = boost::algorithm::to_upper_copy(axis); + def.default_value = new ConfigOptionString{ " "+label }; + Option option = Option(def, axis + "_axis_legend"); + line.append_option(option); + } + optgroup->append_line(line); + + + // Settings table optgroup->append_line(add_og_to_object_settings(L("Position"), L("mm"))); optgroup->append_line(add_og_to_object_settings(L("Rotation"), "°")); - optgroup->append_line(add_og_to_object_settings(L("Scale"), "%")); + optgroup->append_line(add_og_to_object_settings(L("Scale"), "mm")); - optgroup->set_flag(ogDEFAULT); def.label = L("Place on bed"); def.type = coBool; @@ -591,8 +607,6 @@ void add_object_settings(wxWindow* parent, wxBoxSizer* sizer) optgroup->disable(); get_optgroups().push_back(optgroup); // ogFrequentlyObjectSettings - -// add_current_settings(); } @@ -1557,6 +1571,11 @@ void update_rotation_value(const double angle, const std::string& axis) og->set_value("rotation_"+axis, deg); } +void set_uniform_scaling(const bool uniform_scale) +{ + g_is_uniform_scale = uniform_scale; +} + void on_begin_drag(wxDataViewEvent &event) { wxDataViewItem item(event.GetItem()); diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp index 40dfb9279..f8b08d3a6 100644 --- a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp +++ b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp @@ -113,6 +113,7 @@ void update_scale_values(const Vec3d& size, float scale); void update_rotation_values(); // update rotation value after "gizmos" void update_rotation_value(const double angle, const std::string& axis); +void set_uniform_scaling(const bool uniform_scale); void on_begin_drag(wxDataViewEvent &event); void on_drop_possible(wxDataViewEvent &event); diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/xs/src/slic3r/GUI/OptionsGroup.cpp index 453a2f3f7..52485599e 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.cpp +++ b/xs/src/slic3r/GUI/OptionsGroup.cpp @@ -181,8 +181,18 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* wxDefaultPosition, wxSize(label_width, -1), label_style); label->SetFont(label_font); label->Wrap(label_width); // avoid a Linux/GTK bug - grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | - (m_flag == ogSIDE_OPTIONS_VERTICAL ? wxTOP : wxALIGN_CENTER_VERTICAL), 5); + if (!line.near_label_widget) + grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | + (m_flag == ogSIDE_OPTIONS_VERTICAL ? wxTOP : wxALIGN_CENTER_VERTICAL), 5); + else { + // If we're here, we have some widget near the label + // so we need a horizontal sizer to arrange these things + auto sizer = new wxBoxSizer(wxHORIZONTAL); + grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1); + sizer->Add(line.near_label_widget(parent()), 0, wxRIGHT, 2); + sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | + (m_flag == ogSIDE_OPTIONS_VERTICAL ? wxTOP : wxALIGN_CENTER_VERTICAL), 5); + } if (line.label_tooltip.compare("") != 0) label->SetToolTip(line.label_tooltip); } diff --git a/xs/src/slic3r/GUI/OptionsGroup.hpp b/xs/src/slic3r/GUI/OptionsGroup.hpp index 4f263f5e3..5a18803a6 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.hpp +++ b/xs/src/slic3r/GUI/OptionsGroup.hpp @@ -57,6 +57,7 @@ public: size_t full_width {0}; wxSizer* sizer {nullptr}; widget_t widget {nullptr}; + std::function near_label_widget{ nullptr }; void append_option(const Option& option) { m_options.push_back(option); @@ -178,6 +179,8 @@ public: #endif /* __WXGTK__ */ } + wxGridSizer* get_grid_sizer(){ return m_grid_sizer; } + protected: std::map m_options; wxWindow* m_parent {nullptr}; diff --git a/xs/src/slic3r/GUI/wxExtensions.cpp b/xs/src/slic3r/GUI/wxExtensions.cpp index 7fcad9e65..8ee7881e3 100644 --- a/xs/src/slic3r/GUI/wxExtensions.cpp +++ b/xs/src/slic3r/GUI/wxExtensions.cpp @@ -1402,4 +1402,52 @@ void PrusaDoubleSlider::OnRightUp(wxMouseEvent& event) event.Skip(); } + +// ---------------------------------------------------------------------------- +// PrusaLockButton +// ---------------------------------------------------------------------------- + +PrusaLockButton::PrusaLockButton( wxWindow *parent, + wxWindowID id, + const wxPoint& pos /*= wxDefaultPosition*/, + const wxSize& size /*= wxDefaultSize*/): + wxButton(parent, id, wxEmptyString, pos, size, wxBU_EXACTFIT | wxNO_BORDER) +{ + m_bmp_lock_on = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("one_layer_lock_on.png")), wxBITMAP_TYPE_PNG); + m_bmp_lock_off = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("one_layer_lock_off.png")), wxBITMAP_TYPE_PNG); + m_bmp_unlock_on = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("one_layer_unlock_on.png")), wxBITMAP_TYPE_PNG); + m_bmp_unlock_off = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("one_layer_unlock_off.png")), wxBITMAP_TYPE_PNG); + m_lock_icon_dim = m_bmp_lock_on.GetSize().x; + +#ifdef __WXMSW__ + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif // __WXMSW__ + SetBitmap(m_bmp_unlock_on); + + //button events + Bind(wxEVT_BUTTON, &PrusaLockButton::OnButton, this); + Bind(wxEVT_ENTER_WINDOW, &PrusaLockButton::OnEnterBtn, this); + Bind(wxEVT_LEAVE_WINDOW, &PrusaLockButton::OnLeaveBtn, this); +} + +void PrusaLockButton::OnButton(wxCommandEvent& event) +{ + m_is_pushed = !m_is_pushed; + enter_button(true); + + event.Skip(); +} + +void PrusaLockButton::enter_button(const bool enter) +{ + wxBitmap* icon = m_is_pushed ? + enter ? &m_bmp_lock_off : &m_bmp_lock_on : + enter ? &m_bmp_unlock_off : &m_bmp_unlock_on; + SetBitmap(*icon); + + Refresh(); + Update(); +} + // ***************************************************************************** + diff --git a/xs/src/slic3r/GUI/wxExtensions.hpp b/xs/src/slic3r/GUI/wxExtensions.hpp index 064ce1038..465101e3f 100644 --- a/xs/src/slic3r/GUI/wxExtensions.hpp +++ b/xs/src/slic3r/GUI/wxExtensions.hpp @@ -521,6 +521,7 @@ public: long style = wxSL_HORIZONTAL, const wxValidator& val = wxDefaultValidator, const wxString& name = wxEmptyString); + ~PrusaDoubleSlider(){} int GetLowerValue() const { return m_lower_value; @@ -614,7 +615,7 @@ private: wxRect m_rect_one_layer_icon; wxSize m_thumb_size; int m_tick_icon_dim; - int m_lock_icon_dim = 16; + int m_lock_icon_dim; long m_style; float m_label_koef = 1.0; @@ -634,6 +635,41 @@ private: std::set m_ticks; std::vector m_values; }; + + +// ---------------------------------------------------------------------------- +// PrusaLockButton +// ---------------------------------------------------------------------------- + +class PrusaLockButton : public wxButton +{ +public: + PrusaLockButton( + wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize); + ~PrusaLockButton(){} + + void OnButton(wxCommandEvent& event); + void OnEnterBtn(wxMouseEvent& event){ enter_button(true); event.Skip(); } + void OnLeaveBtn(wxMouseEvent& event){ enter_button(false); event.Skip(); } + + bool IsLocked() const { return m_is_pushed; } + +protected: + void enter_button(const bool enter); + +private: + bool m_is_pushed = false; + + wxBitmap m_bmp_lock_on; + wxBitmap m_bmp_lock_off; + wxBitmap m_bmp_unlock_on; + wxBitmap m_bmp_unlock_off; + + int m_lock_icon_dim; +}; // ******************************************************************************************