From 980c6673d42e561d7bf53937e8213e2ce1f0e943 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 5 Jun 2019 11:23:30 +0200 Subject: [PATCH] Reset buttons - fixed rotation of instances with multiple volumes Mirroring buttons now hide where appropriate --- resources/icons/mirroring_off.png | Bin 0 -> 589 bytes resources/icons/mirroring_on.png | Bin 0 -> 600 bytes resources/icons/mirroring_transparent.png | Bin 0 -> 93 bytes src/slic3r/GUI/GUI_ObjectManipulation.cpp | 104 +++++++++++++++------- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 12 ++- 5 files changed, 83 insertions(+), 33 deletions(-) create mode 100644 resources/icons/mirroring_off.png create mode 100644 resources/icons/mirroring_on.png create mode 100644 resources/icons/mirroring_transparent.png diff --git a/resources/icons/mirroring_off.png b/resources/icons/mirroring_off.png new file mode 100644 index 0000000000000000000000000000000000000000..c16655271a7e10d9d83047189086d4d6b509abc3 GIT binary patch literal 589 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S0wixl{&NRXEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8ZEE?e4>iGH4#PT$HOWYUVmw=D)W4<$2R?NV2M}KA?FdtNTmJp~!15S*|LT8;MoC zXsZ3%W24$-moh2c@9l*fmo+q>Gq62KSXA699k*xgMiDE{G|yhA4QhurtG<}@uu!C_ z<$>}m-=I62B~!k9UHS2l6URxP__|{b{!P~`Som^z%$(k+UE0pWDc5vL>wMPBh1~ac zOgPu;&>~>6W*@_Frwy&D=l0S8q@B+Qm*U`007}-kq7#>;Nm&p5M&yqHoBEQzy zY0CSzuP^(vnT8meSs9vI xnHp;w7+M(^oS(SL7)3*FeoAIqCAtPfD`O*whU@kljsZ0=c)I$ztaD0e0ssxu+3)}W literal 0 HcmV?d00001 diff --git a/resources/icons/mirroring_on.png b/resources/icons/mirroring_on.png new file mode 100644 index 0000000000000000000000000000000000000000..6ddeccbe0a2a82019c5c2efd1773c20c0833c4d4 GIT binary patch literal 600 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S3?yCqj{O5tEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBC{YpM6XNqfL!5oT`ng2Uv7KO- z`>oK>c;wi#w-Y8-9OfwbtPfPmnB?v5!uX#__a2bLS>O>_%)p?h48n{ROYO^mg6t)p zzOL*KxFrR+#s37PM*)TAdb&7gOf=4WlTK;F^nd^Dc_ijpxxR1T zX#3n&TDl=r(%}>cpt3=meXk`S|u=mmKH$V*x Mp00i_>zopr04OBpdH?_b literal 0 HcmV?d00001 diff --git a/resources/icons/mirroring_transparent.png b/resources/icons/mirroring_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..841010fcc14ba7f06f09feae3affb3d9ba64c0f5 GIT binary patch literal 93 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3HQmSQK*5Dp-y;YjHK@SetToolTip(wxString::Format(_(L("Toggle %s axis mirroring")), boost::algorithm::to_upper_copy(axis))); - m_mirror_buttons[axis] = btn; + wxSize btn_size(em_unit(parent) * mirror_btn_width, em_unit(parent) * mirror_btn_width); + auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_off.png", wxEmptyString, btn_size, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW); + btn->SetToolTip(wxString::Format(_(L("Toggle %s axis mirroring")), label)); + + m_mirror_buttons[axis_idx].first = btn; + m_mirror_buttons[axis_idx].second = mbShown; auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(btn, wxBU_EXACTFIT/* | wxRESERVE_SPACE_EVEN_IF_HIDDEN*/); + sizer->Add(btn); + btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) { - wxWindow* btn = dynamic_cast(e.GetEventObject()); - Axis axis = (btn == m_mirror_buttons["x"] ? X : ( btn == m_mirror_buttons["y"] ? Y : Z)); + Axis axis = (Axis)(axis_idx + X); + if (m_mirror_buttons[axis_idx].second == mbHidden) + return; + GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); Selection& selection = canvas->get_selection(); - GLVolume* volume = const_cast(selection.get_volume(*selection.get_volume_idxs().begin())); - if (selection.is_single_volume() || selection.is_single_modifier()) + if (selection.is_single_volume() || selection.is_single_modifier()) { + GLVolume* volume = const_cast(selection.get_volume(*selection.get_volume_idxs().begin())); volume->set_volume_mirror(axis, -volume->get_volume_mirror(axis)); - else if (selection.is_single_full_instance()) - volume->set_instance_mirror(axis, -volume->get_instance_mirror(axis)); + } + else if (selection.is_single_full_instance()) { + for (unsigned int idx : selection.get_volume_idxs()){ + GLVolume* volume = const_cast(selection.get_volume(idx)); + volume->set_instance_mirror(axis, -volume->get_instance_mirror(axis)); + } + } else return; + canvas->do_mirror(); canvas->set_as_dirty(); UpdateAndShow(true); @@ -238,7 +255,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : }; // Add reset scale button auto reset_scale_button = [=](wxWindow* parent) { - auto btn = new ScalableButton(parent, wxID_ANY, "colorchange_delete_off.png"); + auto btn = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "undo")); btn->SetToolTip(_(L("Reset scale"))); m_reset_scale_button = btn; auto sizer = new wxBoxSizer(wxHORIZONTAL); @@ -255,7 +272,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : else if (option_name == "Rotation") { // Add reset rotation button auto reset_rotation_button = [=](wxWindow* parent) { - auto btn = new ScalableButton(parent, wxID_ANY, "colorchange_delete_off.png"); + auto btn = new ScalableButton(parent, wxID_ANY, ScalableBitmap(parent, "undo")); btn->SetToolTip(_(L("Reset rotation"))); m_reset_rotation_button = btn; auto sizer = new wxBoxSizer(wxHORIZONTAL); @@ -263,12 +280,17 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) { GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); Selection& selection = canvas->get_selection(); - GLVolume* volume = const_cast(selection.get_volume(*selection.get_volume_idxs().begin())); - if (selection.is_single_volume() || selection.is_single_modifier()) + if (selection.is_single_volume() || selection.is_single_modifier()) { + GLVolume* volume = const_cast(selection.get_volume(*selection.get_volume_idxs().begin())); volume->set_volume_rotation(Vec3d::Zero()); - else if (selection.is_single_full_instance()) - volume->set_instance_rotation(Vec3d::Zero()); + } + else if (selection.is_single_full_instance()) { + for (unsigned int idx : selection.get_volume_idxs()){ + GLVolume* volume = const_cast(selection.get_volume(idx)); + volume->set_instance_rotation(Vec3d::Zero()); + } + } else return; @@ -534,25 +556,42 @@ void ObjectManipulation::update_mirror_buttons_visibility() { GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); Selection& selection = canvas->get_selection(); - std::array show = {false, false, false}; + std::array new_states = {mbHidden, mbHidden, mbHidden}; - if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) { - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - Vec3d mirror; + if (!m_world_coordinates) { + if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) { + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + Vec3d mirror; - if (selection.is_single_full_instance()) - mirror = volume->get_instance_mirror(); - else - mirror = volume->get_volume_mirror(); + if (selection.is_single_full_instance()) + mirror = volume->get_instance_mirror(); + else + mirror = volume->get_volume_mirror(); - for (unsigned char i=0; i<3; ++i) - show[i] = mirror[i] < 0.; + for (unsigned char i=0; i<3; ++i) + new_states[i] = (mirror[i] < 0. ? mbActive : mbShown); + } + } + else { + // the mirroring buttons should be hidden in world coordinates, + // unless we make it actually mirror in world coords. } - wxGetApp().CallAfter([this, show]{ - m_mirror_buttons["x"]->SetBitmap(show[0] ? m_mirror_bitmap_on.bmp() : m_mirror_bitmap_off.bmp()); - m_mirror_buttons["y"]->SetBitmap(show[1] ? m_mirror_bitmap_on.bmp() : m_mirror_bitmap_off.bmp()); - m_mirror_buttons["z"]->SetBitmap(show[2] ? m_mirror_bitmap_on.bmp() : m_mirror_bitmap_off.bmp()); + // Hiding the buttons through Hide() always messed up the sizers. As a workaround, the button + // is assigned a transparent bitmap. We must of course remember the actual state. + wxGetApp().CallAfter([this, new_states]{ + for (int i=0; i<3; ++i) { + if (new_states[i] != m_mirror_buttons[i].second) { + const wxBitmap* bmp; + switch (new_states[i]) { + case mbHidden : bmp = &m_mirror_bitmap_hidden.bmp(); m_mirror_buttons[i].first->Enable(false); break; + case mbShown : bmp = &m_mirror_bitmap_off.bmp(); m_mirror_buttons[i].first->Enable(true); break; + case mbActive : bmp = &m_mirror_bitmap_on.bmp(); m_mirror_buttons[i].first->Enable(true); break; + } + m_mirror_buttons[i].first->SetBitmap(*bmp); + m_mirror_buttons[i].second = new_states[i]; + } + } }); } @@ -817,6 +856,7 @@ void ObjectManipulation::msw_rescale() 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(); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 11b07cda6..cc2154514 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -56,9 +56,19 @@ class ObjectManipulation : public OG_Settings // Non-owning pointers to the reset buttons, so we can hide and show them. ScalableButton* m_reset_scale_button = nullptr; ScalableButton* m_reset_rotation_button = nullptr; - std::map m_mirror_buttons; + + // Mirroring buttons and their current state + enum MirrorButtonState { + mbHidden, + mbShown, + mbActive + }; + std::array, 3> m_mirror_buttons; + + // Bitmaps for the mirroring buttons. ScalableBitmap m_mirror_bitmap_on; ScalableBitmap m_mirror_bitmap_off; + ScalableBitmap m_mirror_bitmap_hidden; // Needs to be updated from OnIdle? bool m_dirty = false;