diff options
Diffstat (limited to 'src/slic3r/GUI/GUI_ObjectManipulation.cpp')
-rw-r--r-- | src/slic3r/GUI/GUI_ObjectManipulation.cpp | 146 |
1 files changed, 108 insertions, 38 deletions
diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 36293525a..8a4c28096 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -2,12 +2,16 @@ #include "GUI_ObjectList.hpp" #include "I18N.hpp" +#include "GLCanvas3D.hpp" #include "OptionsGroup.hpp" +#include "GUI_App.hpp" #include "wxExtensions.hpp" -#include "PresetBundle.hpp" +#include "libslic3r/PresetBundle.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/Geometry.hpp" #include "Selection.hpp" +#include "Plater.hpp" +#include "MainFrame.hpp" #include <boost/algorithm/string.hpp> #include "slic3r/Utils/FixModelByWin10.hpp" @@ -17,6 +21,8 @@ namespace Slic3r namespace GUI { +const double ObjectManipulation::in_to_mm = 25.4; +const double ObjectManipulation::mm_to_in = 0.0393700787; // Helper function to be used by drop to bed button. Returns lowest point of this // volume in world coordinate system. @@ -59,8 +65,8 @@ static wxBitmapComboBox* create_word_local_combo(wxWindow *parent) temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT); - temp->Append(_(L("World coordinates"))); - temp->Append(_(L("Local coordinates"))); + temp->Append(_L("World coordinates")); + temp->Append(_L("Local coordinates")); temp->SetSelection(0); temp->SetValue(temp->GetString(0)); @@ -79,7 +85,7 @@ static wxBitmapComboBox* create_word_local_combo(wxWindow *parent) temp->SetItemBitmap(0, empty_bmp); #endif - temp->SetToolTip(_(L("Select coordinate space, in which the transformation will be performed."))); + temp->SetToolTip(_L("Select coordinate space, in which the transformation will be performed.")); return temp; } @@ -102,8 +108,8 @@ void msw_rescale_word_local_combo(wxBitmapComboBox* combo) // Set rescaled size combo->SetSize(size); - combo->Append(_(L("World coordinates"))); - combo->Append(_(L("Local coordinates"))); + combo->Append(_L("World coordinates")); + combo->Append(_L("Local coordinates")); wxBitmap empty_bmp(1, combo->GetFont().GetPixelSize().y + 2); empty_bmp.SetWidth(0); @@ -121,6 +127,8 @@ static void set_font_and_background_style(wxWindow* win, const wxFont& font) ObjectManipulation::ObjectManipulation(wxWindow* parent) : OG_Settings(parent, true) { + m_imperial_units = wxGetApp().app_config->get("use_inches") == "1"; + m_manifold_warning_bmp = ScalableBitmap(parent, "exclamation"); // Load bitmaps to be used for the mirroring buttons: @@ -150,9 +158,9 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : sizer->Add(m_fix_throught_netfab_bitmap); - auto name_label = new wxStaticText(m_parent, wxID_ANY, _(L("Name"))+":"); + auto name_label = new wxStaticText(m_parent, wxID_ANY, _L("Name")+":"); set_font_and_background_style(name_label, wxGetApp().normal_font()); - name_label->SetToolTip(_(L("Object name"))); + name_label->SetToolTip(_L("Object name")); sizer->Add(name_label); m_main_grid_sizer->Add(sizer); @@ -260,7 +268,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : // We will add a button to toggle mirroring to each axis: auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_off", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW); - btn->SetToolTip(wxString::Format(_(L("Toggle %c axis mirroring")), (int)label)); + btn->SetToolTip(wxString::Format(_L("Toggle %c axis mirroring"), (int)label)); btn->SetBitmapDisabled_(m_mirror_bitmap_hidden); m_mirror_buttons[axis_idx].first = btn; @@ -314,15 +322,15 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : }; // add Units - auto add_unit_text = [this, parent, editors_grid_sizer, height](std::string unit) + auto add_unit_text = [this, parent, editors_grid_sizer, height](std::string unit, wxStaticText** unit_text) { - wxStaticText* unit_text = new wxStaticText(parent, wxID_ANY, _(unit)); - set_font_and_background_style(unit_text, wxGetApp().normal_font()); + *unit_text = new wxStaticText(parent, wxID_ANY, _(unit)); + set_font_and_background_style(*unit_text, wxGetApp().normal_font()); // Unit text should be the same height as labels wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); sizer->SetMinSize(wxSize(-1, height)); - sizer->Add(unit_text, 0, wxALIGN_CENTER_VERTICAL); + sizer->Add(*unit_text, 0, wxALIGN_CENTER_VERTICAL); editors_grid_sizer->Add(sizer); m_rescalable_sizers.push_back(sizer); @@ -330,11 +338,11 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : for (size_t axis_idx = 0; axis_idx < sizeof(axes); axis_idx++) add_edit_boxes("position", axis_idx); - add_unit_text(L("mm")); + add_unit_text(m_imperial_units ? L("in") : L("mm"), &m_position_unit); // Add drop to bed button m_drop_to_bed_button = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "drop_to_bed")); - m_drop_to_bed_button->SetToolTip(_(L("Drop to bed"))); + m_drop_to_bed_button->SetToolTip(_L("Drop to bed")); m_drop_to_bed_button->Bind(wxEVT_BUTTON, [=](wxCommandEvent& e) { // ??? GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); @@ -346,7 +354,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : const Geometry::Transformation& instance_trafo = volume->get_instance_transformation(); Vec3d diff = m_cache.position - instance_trafo.get_matrix(true).inverse() * Vec3d(0., 0., get_volume_min_z(volume)); - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Drop to bed"))); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed")); change_position_value(0, diff.x()); change_position_value(1, diff.y()); change_position_value(2, diff.z()); @@ -356,11 +364,12 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : for (size_t axis_idx = 0; axis_idx < sizeof(axes); axis_idx++) add_edit_boxes("rotation", axis_idx); - add_unit_text("°"); + wxStaticText* rotation_unit{ nullptr }; + add_unit_text("°", &rotation_unit); // Add reset rotation button m_reset_rotation_button = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "undo")); - m_reset_rotation_button->SetToolTip(_(L("Reset rotation"))); + m_reset_rotation_button->SetToolTip(_L("Reset rotation")); m_reset_rotation_button->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) { GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); Selection& selection = canvas->get_selection(); @@ -390,13 +399,14 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : for (size_t axis_idx = 0; axis_idx < sizeof(axes); axis_idx++) add_edit_boxes("scale", axis_idx); - add_unit_text("%"); + wxStaticText* scale_unit{ nullptr }; + add_unit_text("%", &scale_unit); // Add reset scale button m_reset_scale_button = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "undo")); - m_reset_scale_button->SetToolTip(_(L("Reset scale"))); + m_reset_scale_button->SetToolTip(_L("Reset scale")); m_reset_scale_button->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) { - Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Reset scale"))); + Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset scale")); change_scale_value(0, 100.); change_scale_value(1, 100.); change_scale_value(2, 100.); @@ -405,11 +415,23 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : for (size_t axis_idx = 0; axis_idx < sizeof(axes); axis_idx++) add_edit_boxes("size", axis_idx); - add_unit_text("mm"); + add_unit_text(m_imperial_units ? L("in") : L("mm"), &m_size_unit); editors_grid_sizer->AddStretchSpacer(1); m_main_grid_sizer->Add(editors_grid_sizer, 1, wxEXPAND); + m_check_inch = new wxCheckBox(parent, wxID_ANY, _L("Inches")); + m_check_inch->SetFont(wxGetApp().normal_font()); + + m_check_inch->SetValue(m_imperial_units); + m_check_inch->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { + wxGetApp().app_config->set("use_inches", m_check_inch->GetValue() ? "1" : "0"); + wxGetApp().sidebar().update_ui_from_settings(); + }); + + m_main_grid_sizer->Add(m_check_inch, 1, wxEXPAND); + + m_og->activate(); m_og->sizer->Clear(true); m_og->sizer->Add(m_main_grid_sizer, 1, wxEXPAND | wxALL, border); } @@ -452,6 +474,32 @@ void ObjectManipulation::UpdateAndShow(const bool show) OG_Settings::UpdateAndShow(show); } +void ObjectManipulation::update_ui_from_settings() +{ + if (m_imperial_units != (wxGetApp().app_config->get("use_inches") == "1")) { + m_imperial_units = wxGetApp().app_config->get("use_inches") == "1"; + + auto update_unit_text = [](const wxString& new_unit_text, wxStaticText* widget) { + widget->SetLabel(new_unit_text); + if (wxOSX) set_font_and_background_style(widget, wxGetApp().normal_font()); + }; + update_unit_text(m_imperial_units ? _L("in") : _L("mm"), m_position_unit); + update_unit_text(m_imperial_units ? _L("in") : _L("mm"), m_size_unit); + + for (int i = 0; i < 3; ++i) { + auto update = [this, i](/*ManipulationEditorKey*/int key_id, const Vec3d& new_value) { + wxString new_text = double_to_string(m_imperial_units ? new_value(i) * mm_to_in : new_value(i), 2); + const int id = key_id * 3 + i; + if (id >= 0) m_editors[id]->set_value(new_text); + }; + update(0/*mePosition*/, m_new_position); + update(3/*meSize*/, m_new_size); + } + } + + m_check_inch->SetValue(m_imperial_units); +} + void ObjectManipulation::update_settings_value(const Selection& selection) { m_new_move_label_string = L("Position"); @@ -462,8 +510,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_world_coordinates = true; ObjectList* obj_list = wxGetApp().obj_list(); - if (selection.is_single_full_instance()) - { + if (selection.is_single_full_instance()) { // all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); m_new_position = volume->get_instance_offset(); @@ -481,7 +528,8 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_rotation = Vec3d::Zero(); m_new_size = selection.get_scaled_instance_bounding_box().size(); m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.; - } else { + } + else { m_new_rotation = volume->get_instance_rotation() * (180. / M_PI); m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size()); m_new_scale = volume->get_instance_scaling_factor() * 100.; @@ -489,8 +537,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_enabled = true; } - else if (selection.is_single_full_object() && obj_list->is_selected(itObject)) - { + else if (selection.is_single_full_object() && obj_list->is_selected(itObject)) { const BoundingBoxf3& box = selection.get_bounding_box(); m_new_position = box.center(); m_new_rotation = Vec3d::Zero(); @@ -500,18 +547,16 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_scale_label_string = L("Scale"); m_new_enabled = true; } - else if (selection.is_single_modifier() || selection.is_single_volume()) - { + else if (selection.is_single_modifier() || selection.is_single_volume()) { // the selection contains a single volume const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); m_new_position = volume->get_volume_offset(); m_new_rotation = volume->get_volume_rotation() * (180. / M_PI); m_new_scale = volume->get_volume_scaling_factor() * 100.; - m_new_size = volume->get_volume_transformation().get_scaling_factor().cwiseProduct(volume->bounding_box().size()); + m_new_size = volume->get_instance_transformation().get_scaling_factor().cwiseProduct(volume->get_volume_transformation().get_scaling_factor().cwiseProduct(volume->bounding_box().size())); m_new_enabled = true; } - else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) - { + else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) { reset_settings_value(); m_new_move_label_string = L("Translate"); m_new_rotate_label_string = L("Rotate"); @@ -562,6 +607,8 @@ void ObjectManipulation::update_if_dirty() if (std::abs(cached_rounded(i) - new_rounded) > EPSILON) { cached_rounded(i) = new_rounded; const int id = key_id*3+i; + if (m_imperial_units && (key_id == mePosition || key_id == meSize)) + new_text = double_to_string(new_value(i)*mm_to_in, 2); if (id >= 0) m_editors[id]->set_value(new_text); } cached(i) = new_value(i); @@ -575,7 +622,7 @@ void ObjectManipulation::update_if_dirty() if (selection.requires_uniform_scale()) { m_lock_bnt->SetLock(true); - m_lock_bnt->SetToolTip(_(L("You cannot use non-uniform scaling mode for multiple objects/parts selection"))); + m_lock_bnt->SetToolTip(_L("You cannot use non-uniform scaling mode for multiple objects/parts selection")); m_lock_bnt->disable(); } else { @@ -851,6 +898,9 @@ void ObjectManipulation::on_change(const std::string& opt_key, int axis, double if (!m_cache.is_valid()) return; + if (m_imperial_units && (opt_key == "position" || opt_key == "size")) + new_value *= in_to_mm; + if (opt_key == "position") change_position_value(axis, new_value); else if (opt_key == "rotation") @@ -872,11 +922,11 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value) if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) { // Cannot apply scaling in the world coordinate system. wxMessageDialog dlg(GUI::wxGetApp().mainframe, - _(L("The currently manipulated object is tilted (rotation angles are not multiples of 90°).\n" + _L("The currently manipulated object is tilted (rotation angles are not multiples of 90°).\n" "Non-uniform scaling of tilted objects is only possible in the World coordinate system,\n" - "once the rotation is embedded into the object coordinates.")) + "\n" + - _(L("This operation is irreversible.\n" - "Do you want to proceed?")), + "once the rotation is embedded into the object coordinates.") + "\n" + + _L("This operation is irreversible.\n" + "Do you want to proceed?"), SLIC3R_APP_NAME, wxYES_NO | wxCANCEL | wxCANCEL_DEFAULT | wxICON_QUESTION); if (dlg.ShowModal() != wxID_YES) { @@ -929,15 +979,35 @@ void ObjectManipulation::msw_rescale() for (ManipulationEditor* editor : m_editors) editor->msw_rescale(); + // rescale "inches" checkbox + m_check_inch->SetMinSize(wxSize(-1, int(1.5f * m_check_inch->GetFont().GetPixelSize().y + 0.5f))); + get_og()->msw_rescale(); } +void ObjectManipulation::sys_color_changed() +{ + // btn...->msw_rescale() updates icon on button, so use it + m_mirror_bitmap_on.msw_rescale(); + m_mirror_bitmap_off.msw_rescale(); + m_mirror_bitmap_hidden.msw_rescale(); + m_reset_scale_button->msw_rescale(); + m_reset_rotation_button->msw_rescale(); + m_drop_to_bed_button->msw_rescale(); + m_lock_bnt->msw_rescale(); + + for (int id = 0; id < 3; ++id) + m_mirror_buttons[id].first->msw_rescale(); + + get_og()->sys_color_changed(); +} + static const char axes[] = { 'x', 'y', 'z' }; ManipulationEditor::ManipulationEditor(ObjectManipulation* parent, const std::string& opt_key, int axis) : wxTextCtrl(parent->parent(), wxID_ANY, wxEmptyString, wxDefaultPosition, - wxSize(5*int(wxGetApp().em_unit()), wxDefaultCoord), wxTE_PROCESS_ENTER), + wxSize((wxOSX ? 5 : 6)*int(wxGetApp().em_unit()), wxDefaultCoord), wxTE_PROCESS_ENTER), m_opt_key(opt_key), m_axis(axis) { |