Reset buttons - fixed rotation of instances with multiple volumes

Mirroring buttons now hide where appropriate
This commit is contained in:
Lukas Matena 2019-06-05 11:23:30 +02:00
parent a3c1644ead
commit 980c6673d4
5 changed files with 83 additions and 33 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 B

View File

@ -172,33 +172,50 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
def.type = coString; def.type = coString;
def.width = field_width - mirror_btn_width;//field_width/*50*/; def.width = field_width - mirror_btn_width;//field_width/*50*/;
// Load bitmaps to be used for the mirroring buttons:
m_mirror_bitmap_on = ScalableBitmap(parent, "mirroring_on.png");
m_mirror_bitmap_off = ScalableBitmap(parent, "mirroring_off.png");
m_mirror_bitmap_hidden = ScalableBitmap(parent, "mirroring_transparent.png");
for (const std::string axis : { "x", "y", "z" }) { for (const std::string axis : { "x", "y", "z" }) {
const std::string label = boost::algorithm::to_upper_copy(axis); const std::string label = boost::algorithm::to_upper_copy(axis);
def.set_default_value(new ConfigOptionString{ " " + label }); def.set_default_value(new ConfigOptionString{ " " + label });
Option option = Option(def, axis + "_axis_legend"); Option option = Option(def, axis + "_axis_legend");
unsigned int axis_idx = (axis[0] - 'x'); // 0, 1 or 2
// We will add a button to toggle mirroring to each axis: // We will add a button to toggle mirroring to each axis:
auto mirror_button = [=](wxWindow* parent) { auto mirror_button = [=](wxWindow* parent) {
m_mirror_bitmap_on = ScalableBitmap(parent, "colorchange_add_on.png"); wxSize btn_size(em_unit(parent) * mirror_btn_width, em_unit(parent) * mirror_btn_width);
m_mirror_bitmap_off = ScalableBitmap(parent, "colorchange_delete_off.png"); auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_off.png", wxEmptyString, btn_size, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW);
auto btn = new ScalableButton(parent, wxID_ANY, "colorchange_delete_off.png", wxEmptyString, wxSize(em_unit(parent) * mirror_btn_width, em_unit(parent) * mirror_btn_width)); btn->SetToolTip(wxString::Format(_(L("Toggle %s axis mirroring")), label));
btn->SetToolTip(wxString::Format(_(L("Toggle %s axis mirroring")), boost::algorithm::to_upper_copy(axis)));
m_mirror_buttons[axis] = btn; m_mirror_buttons[axis_idx].first = btn;
m_mirror_buttons[axis_idx].second = mbShown;
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn, wxBU_EXACTFIT/* | wxRESERVE_SPACE_EVEN_IF_HIDDEN*/); sizer->Add(btn);
btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) { btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) {
wxWindow* btn = dynamic_cast<wxWindow*>(e.GetEventObject()); Axis axis = (Axis)(axis_idx + X);
Axis axis = (btn == m_mirror_buttons["x"] ? X : ( btn == m_mirror_buttons["y"] ? Y : Z)); if (m_mirror_buttons[axis_idx].second == mbHidden)
return;
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection(); Selection& selection = canvas->get_selection();
GLVolume* volume = const_cast<GLVolume*>(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<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin()));
volume->set_volume_mirror(axis, -volume->get_volume_mirror(axis)); 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<GLVolume*>(selection.get_volume(idx));
volume->set_instance_mirror(axis, -volume->get_instance_mirror(axis));
}
}
else else
return; return;
canvas->do_mirror(); canvas->do_mirror();
canvas->set_as_dirty(); canvas->set_as_dirty();
UpdateAndShow(true); UpdateAndShow(true);
@ -238,7 +255,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
}; };
// Add reset scale button // Add reset scale button
auto reset_scale_button = [=](wxWindow* parent) { 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"))); btn->SetToolTip(_(L("Reset scale")));
m_reset_scale_button = btn; m_reset_scale_button = btn;
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
@ -255,7 +272,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
else if (option_name == "Rotation") { else if (option_name == "Rotation") {
// Add reset rotation button // Add reset rotation button
auto reset_rotation_button = [=](wxWindow* parent) { 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"))); btn->SetToolTip(_(L("Reset rotation")));
m_reset_rotation_button = btn; m_reset_rotation_button = btn;
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
@ -263,12 +280,17 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) { btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) {
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection(); Selection& selection = canvas->get_selection();
GLVolume* volume = const_cast<GLVolume*>(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<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin()));
volume->set_volume_rotation(Vec3d::Zero()); 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<GLVolume*>(selection.get_volume(idx));
volume->set_instance_rotation(Vec3d::Zero());
}
}
else else
return; return;
@ -534,25 +556,42 @@ void ObjectManipulation::update_mirror_buttons_visibility()
{ {
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection(); Selection& selection = canvas->get_selection();
std::array<bool, 3> show = {false, false, false}; std::array<MirrorButtonState, 3> new_states = {mbHidden, mbHidden, mbHidden};
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) { if (!m_world_coordinates) {
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
Vec3d mirror; const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
Vec3d mirror;
if (selection.is_single_full_instance()) if (selection.is_single_full_instance())
mirror = volume->get_instance_mirror(); mirror = volume->get_instance_mirror();
else else
mirror = volume->get_volume_mirror(); mirror = volume->get_volume_mirror();
for (unsigned char i=0; i<3; ++i) for (unsigned char i=0; i<3; ++i)
show[i] = mirror[i] < 0.; 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]{ // Hiding the buttons through Hide() always messed up the sizers. As a workaround, the button
m_mirror_buttons["x"]->SetBitmap(show[0] ? m_mirror_bitmap_on.bmp() : m_mirror_bitmap_off.bmp()); // is assigned a transparent bitmap. We must of course remember the actual state.
m_mirror_buttons["y"]->SetBitmap(show[1] ? m_mirror_bitmap_on.bmp() : m_mirror_bitmap_off.bmp()); wxGetApp().CallAfter([this, new_states]{
m_mirror_buttons["z"]->SetBitmap(show[2] ? m_mirror_bitmap_on.bmp() : m_mirror_bitmap_off.bmp()); 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_on.msw_rescale();
m_mirror_bitmap_off.msw_rescale(); m_mirror_bitmap_off.msw_rescale();
m_mirror_bitmap_hidden.msw_rescale();
m_reset_scale_button->msw_rescale(); m_reset_scale_button->msw_rescale();
m_reset_rotation_button->msw_rescale(); m_reset_rotation_button->msw_rescale();

View File

@ -56,9 +56,19 @@ class ObjectManipulation : public OG_Settings
// Non-owning pointers to the reset buttons, so we can hide and show them. // Non-owning pointers to the reset buttons, so we can hide and show them.
ScalableButton* m_reset_scale_button = nullptr; ScalableButton* m_reset_scale_button = nullptr;
ScalableButton* m_reset_rotation_button = nullptr; ScalableButton* m_reset_rotation_button = nullptr;
std::map<std::string, ScalableButton*> m_mirror_buttons;
// Mirroring buttons and their current state
enum MirrorButtonState {
mbHidden,
mbShown,
mbActive
};
std::array<std::pair<ScalableButton*, MirrorButtonState>, 3> m_mirror_buttons;
// Bitmaps for the mirroring buttons.
ScalableBitmap m_mirror_bitmap_on; ScalableBitmap m_mirror_bitmap_on;
ScalableBitmap m_mirror_bitmap_off; ScalableBitmap m_mirror_bitmap_off;
ScalableBitmap m_mirror_bitmap_hidden;
// Needs to be updated from OnIdle? // Needs to be updated from OnIdle?
bool m_dirty = false; bool m_dirty = false;