Added mirroring buttons into object manipulation panel

This commit is contained in:
Lukas Matena 2019-06-03 10:40:15 +02:00
parent 9f236bc603
commit a3c1644ead
2 changed files with 77 additions and 3 deletions

View File

@ -92,6 +92,7 @@ void msw_rescale_word_local_combo(wxBitmapComboBox* combo)
combo->SetValue(selection); combo->SetValue(selection);
} }
ObjectManipulation::ObjectManipulation(wxWindow* parent) : ObjectManipulation::ObjectManipulation(wxWindow* parent) :
OG_Settings(parent, true) OG_Settings(parent, true)
#ifndef __APPLE__ #ifndef __APPLE__
@ -162,16 +163,50 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
const int field_width = 5; const int field_width = 5;
// Mirror button size:
const int mirror_btn_width = 3;
// Legend for object modification // Legend for object modification
line = Line{ "", "" }; line = Line{ "", "" };
def.label = ""; def.label = "";
def.type = coString; def.type = coString;
def.width = field_width/*50*/; def.width = field_width - mirror_btn_width;//field_width/*50*/;
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");
// We will add a button to toggle mirroring to each axis:
auto mirror_button = [=](wxWindow* parent) {
m_mirror_bitmap_on = ScalableBitmap(parent, "colorchange_add_on.png");
m_mirror_bitmap_off = ScalableBitmap(parent, "colorchange_delete_off.png");
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")), boost::algorithm::to_upper_copy(axis)));
m_mirror_buttons[axis] = btn;
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn, wxBU_EXACTFIT/* | wxRESERVE_SPACE_EVEN_IF_HIDDEN*/);
btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) {
wxWindow* btn = dynamic_cast<wxWindow*>(e.GetEventObject());
Axis axis = (btn == m_mirror_buttons["x"] ? X : ( btn == m_mirror_buttons["y"] ? Y : Z));
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
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())
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
return;
canvas->do_mirror();
canvas->set_as_dirty();
UpdateAndShow(true);
});
return sizer;
};
option.side_widget = mirror_button;
line.append_option(option); line.append_option(option);
} }
line.near_label_widget = [this](wxWindow* parent) { line.near_label_widget = [this](wxWindow* parent) {
@ -226,8 +261,6 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn, wxBU_EXACTFIT); sizer->Add(btn, wxBU_EXACTFIT);
btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) { btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent &e) {
// The following makes sure that the LOCAL coordinate system rotation is reset by calling
// methods that are readily available here - it is not nice but gets the work done.
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())); GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin()));
@ -284,6 +317,8 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
}; };
} }
void ObjectManipulation::Show(const bool show) void ObjectManipulation::Show(const bool show)
{ {
if (show != IsShown()) { if (show != IsShown()) {
@ -453,6 +488,7 @@ void ObjectManipulation::update_if_dirty()
m_og->disable(); m_og->disable();
update_reset_buttons_visibility(); update_reset_buttons_visibility();
update_mirror_buttons_visibility();
m_dirty = false; m_dirty = false;
} }
@ -494,6 +530,34 @@ void ObjectManipulation::update_reset_buttons_visibility()
void ObjectManipulation::update_mirror_buttons_visibility()
{
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection();
std::array<bool, 3> show = {false, false, false};
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();
for (unsigned char i=0; i<3; ++i)
show[i] = mirror[i] < 0.;
}
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());
});
}
#ifndef __APPLE__ #ifndef __APPLE__
void ObjectManipulation::emulate_kill_focus() void ObjectManipulation::emulate_kill_focus()
@ -751,6 +815,11 @@ void ObjectManipulation::msw_rescale()
m_manifold_warning_bmp.msw_rescale(); m_manifold_warning_bmp.msw_rescale();
m_fix_throught_netfab_bitmap->SetBitmap(m_manifold_warning_bmp.bmp()); m_fix_throught_netfab_bitmap->SetBitmap(m_manifold_warning_bmp.bmp());
m_mirror_bitmap_on.msw_rescale();
m_mirror_bitmap_off.msw_rescale();
m_reset_scale_button->msw_rescale();
m_reset_rotation_button->msw_rescale();
get_og()->msw_rescale(); get_og()->msw_rescale();
} }

View File

@ -56,6 +56,9 @@ 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;
ScalableBitmap m_mirror_bitmap_on;
ScalableBitmap m_mirror_bitmap_off;
// Needs to be updated from OnIdle? // Needs to be updated from OnIdle?
bool m_dirty = false; bool m_dirty = false;
@ -117,6 +120,8 @@ private:
// Show or hide scale/rotation reset buttons if needed // Show or hide scale/rotation reset buttons if needed
void update_reset_buttons_visibility(); void update_reset_buttons_visibility();
//Show or hide mirror buttons
void update_mirror_buttons_visibility();
// change values // change values
void change_position_value(int axis, double value); void change_position_value(int axis, double value);