From 1c0bc8a5f3e2825337cbb94c33609c749bde0146 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 28 Jan 2019 15:50:02 +0100 Subject: [PATCH 1/7] Fixed synchronization between Objects List and Object manipulator table --- src/slic3r/GUI/GLCanvas3D.cpp | 5 ++ src/slic3r/GUI/GUI_ObjectManipulation.cpp | 59 ++++++++--------------- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 18 +++++-- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 7366516d1..28c3baf24 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1617,6 +1617,11 @@ void GLCanvas3D::Selection::clear() _update_type(); m_bounding_box_dirty = true; + +#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION + // resets the cache in the sidebar + wxGetApp().obj_manipul()->reset_cache(); +#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } // Update the selection based on the map from old indices to new indices after m_volumes changed. diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 93e527fe5..b8aa07613 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -23,6 +23,14 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : m_og->set_grid_vgap(5); m_og->m_on_change = [this](const std::string& opt_key, const boost::any& value) { +#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION + // needed to hide the visual hints in 3D scene + wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); + + if (!m_cache.is_valid()) + return; +#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION + std::vector axes{ "_x", "_y", "_z" }; std::string param; @@ -38,26 +46,26 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : else if (param == "rotation") change_rotation_value(new_value); else if (param == "scale") -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION change_scale_value(new_value); -#else - change_scale_value(new_value); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION else if (param == "size") -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION change_size_value(new_value); -#else - change_size_value(new_value); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION +#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); +#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION }; m_og->m_fill_empty_value = [this](const std::string& opt_key) { -#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION +#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION + // needed to hide the visual hints in 3D scene + wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); + + if (!m_cache.is_valid()) + return; +#else this->update_if_dirty(); -#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION +#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION std::string param; std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); @@ -68,45 +76,31 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : int axis = opt_key.back() == 'x' ? 0 : opt_key.back() == 'y' ? 1 : 2; -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION value = m_cache.position(axis); -#else - value = m_cache_position(axis); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } else if (param == "rotation") { int axis = opt_key.back() == 'x' ? 0 : opt_key.back() == 'y' ? 1 : 2; -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION value = m_cache.rotation(axis); -#else - value = m_cache_rotation(axis); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } else if (param == "scale") { int axis = opt_key.back() == 'x' ? 0 : opt_key.back() == 'y' ? 1 : 2; -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION value = m_cache.scale(axis); -#else - value = m_cache_scale(axis); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } else if (param == "size") { int axis = opt_key.back() == 'x' ? 0 : opt_key.back() == 'y' ? 1 : 2; -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION value = m_cache.size(axis); -#else - value = m_cache_size(axis); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } m_og->set_value(opt_key, double_to_string(value)); +#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); +#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION }; m_og->m_set_focus = [this](const std::string& opt_key) @@ -114,6 +108,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : #if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION this->update_if_dirty(); #endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION + // needed to show the visual hints in 3D scene wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, true); }; @@ -459,18 +454,10 @@ void ObjectManipulation::change_position_value(const Vec3d& position) auto canvas = wxGetApp().plater()->canvas3D(); GLCanvas3D::Selection& selection = canvas->get_selection(); selection.start_dragging(); -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION selection.translate(position - m_cache.position, selection.requires_local_axes()); -#else - selection.translate(position - m_cache_position, selection.requires_local_axes()); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION canvas->do_move(); -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION m_cache.position = position; -#else - m_cache_position = position; -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } void ObjectManipulation::change_rotation_value(const Vec3d& rotation) @@ -503,11 +490,7 @@ void ObjectManipulation::change_scale_value(const Vec3d& scale) const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); if (m_uniform_scale || selection.requires_uniform_scale()) { -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs(); -#else - Vec3d abs_scale_diff = (scale - m_cache_scale).cwiseAbs(); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION double max_diff = abs_scale_diff(X); Axis max_diff_axis = X; if (max_diff < abs_scale_diff(Y)) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 1684a1360..4aa3aa5f7 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -43,11 +43,19 @@ class ObjectManipulation : public OG_Settings Instance instance; - Cache() : position(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX)) , rotation(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX)) - , scale(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX)) , size(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX)) - , move_label_string("") , rotate_label_string("") , scale_label_string("") + Cache() { reset(); } + void reset() { + position = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); + rotation = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); + scale = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); + size = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); + move_label_string = ""; + rotate_label_string = ""; + scale_label_string = ""; + instance.reset(); } + bool is_valid() const { return position != Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); } }; Cache m_cache; @@ -92,6 +100,10 @@ public: void set_uniform_scaling(const bool uniform_scale) { m_uniform_scale = uniform_scale;} bool get_uniform_scaling() const { return m_uniform_scale; } +#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION + void reset_cache() { m_cache.reset(); } +#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION + private: void reset_settings_value(); From 6137cc48eb368268c106f95e58b7b2254e7b6412 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 28 Jan 2019 16:06:44 +0100 Subject: [PATCH 2/7] ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION set as default --- src/libslic3r/Technologies.hpp | 2 - src/slic3r/GUI/GLCanvas3D.cpp | 36 ---------- src/slic3r/GUI/GLCanvas3D.hpp | 2 - src/slic3r/GUI/GUI_ObjectManipulation.cpp | 83 ----------------------- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 9 --- src/slic3r/GUI/Plater.cpp | 2 - 6 files changed, 134 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index be37e1694..8bf540974 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -32,8 +32,6 @@ //==================== #define ENABLE_1_42_0_ALPHA2 1 -// Improves navigation between sidebar fields -#define ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION (1 && ENABLE_1_42_0_ALPHA2) // Adds print bed models to 3D scene #define ENABLE_PRINT_BED_MODELS (1 && ENABLE_1_42_0_ALPHA2) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 28c3baf24..107e763c6 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1618,10 +1618,8 @@ void GLCanvas3D::Selection::clear() _update_type(); m_bounding_box_dirty = true; -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION // resets the cache in the sidebar wxGetApp().obj_manipul()->reset_cache(); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } // Update the selection based on the map from old indices to new indices after m_volumes changed. @@ -3987,10 +3985,8 @@ wxDEFINE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_QUESTION_MARK, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_INSTANCES, Event); wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent); -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); @@ -5317,9 +5313,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) bool already_selected = m_selection.contains_volume(m_hover_volume_id); bool shift_down = evt.ShiftDown(); -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION Selection::IndicesList curr_idxs = m_selection.get_volume_idxs(); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION if (already_selected && shift_down) m_selection.remove(m_hover_volume_id); @@ -5336,21 +5330,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #endif // ENABLE_MOVE_MIN_THRESHOLD } -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION if (curr_idxs != m_selection.get_volume_idxs()) { -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION m_gizmos.update_on_off_state(m_selection); _update_gizmos_data(); -#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION - wxGetApp().obj_manipul()->update_settings_value(m_selection); -#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); m_dirty = true; -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } } @@ -5740,7 +5727,6 @@ void GLCanvas3D::do_move() ModelObject* model_object = m_model->objects[object_idx]; if (model_object != nullptr) { -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION if (selection_mode == Selection::Instance) model_object->instances[instance_idx]->set_offset(v->get_instance_offset()); else if (selection_mode == Selection::Volume) @@ -5748,20 +5734,6 @@ void GLCanvas3D::do_move() object_moved = true; model_object->invalidate_bounding_box(); -#else - if (selection_mode == Selection::Instance) - { - model_object->instances[instance_idx]->set_offset(v->get_instance_offset()); - object_moved = true; - } - else if (selection_mode == Selection::Volume) - { - model_object->volumes[volume_idx]->set_offset(v->get_volume_offset()); - object_moved = true; - } - if (object_moved) - model_object->invalidate_bounding_box(); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } } else if (object_idx == 1000) @@ -5832,12 +5804,8 @@ void GLCanvas3D::do_rotate() m->translate_instance(i.second, shift); } -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION if (!done.empty()) post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_ROTATED)); -#else - post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } void GLCanvas3D::do_scale() @@ -5888,12 +5856,8 @@ void GLCanvas3D::do_scale() m->translate_instance(i.second, shift); } -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION if (!done.empty()) post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_ROTATED)); -#else - post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } void GLCanvas3D::do_flatten() diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 8bdbf89b0..22834e0d5 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -125,10 +125,8 @@ wxDECLARE_EVENT(EVT_GLCANVAS_QUESTION_MARK, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_INCREASE_INSTANCES, Event); // data: +1 => increase, -1 => decrease wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index b8aa07613..b4480f7e6 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -23,13 +23,11 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : m_og->set_grid_vgap(5); m_og->m_on_change = [this](const std::string& opt_key, const boost::any& value) { -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION // needed to hide the visual hints in 3D scene wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); if (!m_cache.is_valid()) return; -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION std::vector axes{ "_x", "_y", "_z" }; @@ -49,23 +47,15 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : change_scale_value(new_value); else if (param == "size") change_size_value(new_value); - -#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION - wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); -#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION }; m_og->m_fill_empty_value = [this](const std::string& opt_key) { -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION // needed to hide the visual hints in 3D scene wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); if (!m_cache.is_valid()) return; -#else - this->update_if_dirty(); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION std::string param; std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); @@ -98,16 +88,10 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : } m_og->set_value(opt_key, double_to_string(value)); -#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION - wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); -#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION }; m_og->m_set_focus = [this](const std::string& opt_key) { -#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION - this->update_if_dirty(); -#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION // needed to show the visual hints in 3D scene wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, true); }; @@ -228,9 +212,6 @@ void ObjectManipulation::UpdateAndShow(const bool show) { if (show) { update_settings_value(wxGetApp().plater()->canvas3D()->get_selection()); -#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION - update_if_dirty(); -#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } OG_Settings::UpdateAndShow(show); @@ -249,7 +230,6 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele m_new_rotation = volume->get_instance_rotation(); m_new_scale = volume->get_instance_scaling_factor(); int obj_idx = volume->object_idx(); -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION int instance_idx = volume->instance_idx(); if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size())) { @@ -265,21 +245,12 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele else // this should never happen m_new_size = Vec3d::Zero(); -#else - if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size())) - m_new_size = volume->get_instance_transformation().get_matrix(true, true) * (*wxGetApp().model_objects())[obj_idx]->raw_mesh_bounding_box().size(); - else - // this should never happen - m_new_size = Vec3d::Zero(); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION m_new_enabled = true; } else if (selection.is_single_full_object()) { -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION m_cache.instance.reset(); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION const BoundingBoxf3& box = selection.get_bounding_box(); m_new_position = box.center(); @@ -292,9 +263,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele } else if (selection.is_single_modifier() || selection.is_single_volume()) { -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION m_cache.instance.reset(); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION // the selection contains a single volume const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); @@ -324,7 +293,6 @@ void ObjectManipulation::update_if_dirty() if (!m_dirty) return; -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION if (m_cache.move_label_string != _(m_new_move_label_string)+ ":") { m_cache.move_label_string = _(m_new_move_label_string)+ ":"; @@ -401,37 +369,6 @@ void ObjectManipulation::update_if_dirty() m_og->enable(); else m_og->disable(); -#else - m_move_Label->SetLabel(_(m_new_move_label_string)); - m_rotate_Label->SetLabel(_(m_new_rotate_label_string)); - m_scale_Label->SetLabel(_(m_new_scale_label_string)); - - m_og->set_value("position_x", double_to_string(m_new_position(0), 2)); - m_og->set_value("position_y", double_to_string(m_new_position(1), 2)); - m_og->set_value("position_z", double_to_string(m_new_position(2), 2)); - m_cache_position = m_new_position; - - auto scale = m_new_scale * 100.0; - m_og->set_value("scale_x", double_to_string(scale(0), 2)); - m_og->set_value("scale_y", double_to_string(scale(1), 2)); - m_og->set_value("scale_z", double_to_string(scale(2), 2)); - m_cache_scale = scale; - - m_og->set_value("size_x", double_to_string(m_new_size(0), 2)); - m_og->set_value("size_y", double_to_string(m_new_size(1), 2)); - m_og->set_value("size_z", double_to_string(m_new_size(2), 2)); - m_cache_size = m_new_size; - - m_og->set_value("rotation_x", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(0)), 0), 2)); - m_og->set_value("rotation_y", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(1)), 0), 2)); - m_og->set_value("rotation_z", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(2)), 0), 2)); - m_cache_rotation = m_new_rotation; - - if (m_new_enabled) - m_og->enable(); - else - m_og->disable(); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION m_dirty = false; } @@ -443,9 +380,7 @@ void ObjectManipulation::reset_settings_value() m_new_scale = Vec3d::Ones(); m_new_size = Vec3d::Zero(); m_new_enabled = false; -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION m_cache.instance.reset(); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION m_dirty = true; } @@ -472,16 +407,10 @@ void ObjectManipulation::change_rotation_value(const Vec3d& rotation) } canvas->get_selection().start_dragging(); -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION canvas->get_selection().rotate(rad_rotation, selection.is_single_full_instance() || selection.requires_local_axes()); -#else - canvas->get_selection().rotate(rad_rotation, selection.is_single_full_instance()); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION canvas->do_rotate(); -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION m_cache.rotation = rotation; -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } void ObjectManipulation::change_scale_value(const Vec3d& scale) @@ -513,12 +442,10 @@ void ObjectManipulation::change_scale_value(const Vec3d& scale) canvas->get_selection().scale(scaling_factor, false); canvas->do_scale(); -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION if (!m_cache.scale.isApprox(scale)) m_cache.instance.instance_idx = -1; m_cache.scale = scale; -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } void ObjectManipulation::change_size_value(const Vec3d& size) @@ -526,7 +453,6 @@ void ObjectManipulation::change_size_value(const Vec3d& size) const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); Vec3d ref_size = m_cache.size; -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION if (selection.is_single_volume() || selection.is_single_modifier()) { const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); @@ -564,15 +490,6 @@ void ObjectManipulation::change_size_value(const Vec3d& size) canvas->do_scale(); m_cache.size = size; -#else - if (selection.is_single_full_instance()) - { - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - ref_size = volume->bounding_box.size(); - } - - change_scale_value(100.0 * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2))); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION } } //namespace GUI diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 4aa3aa5f7..b761beda8 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -15,7 +15,6 @@ namespace GUI { class ObjectManipulation : public OG_Settings { -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION struct Cache { Vec3d position; @@ -59,12 +58,6 @@ class ObjectManipulation : public OG_Settings }; Cache m_cache; -#else - Vec3d m_cache_position{ 0., 0., 0. }; - Vec3d m_cache_rotation{ 0., 0., 0. }; - Vec3d m_cache_scale{ 100., 100., 100. }; - Vec3d m_cache_size{ 0., 0., 0. }; -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION wxStaticText* m_move_Label = nullptr; wxStaticText* m_scale_Label = nullptr; @@ -100,9 +93,7 @@ public: void set_uniform_scaling(const bool uniform_scale) { m_uniform_scale = uniform_scale;} bool get_uniform_scaling() const { return m_uniform_scale; } -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION void reset_cache() { m_cache.reset(); } -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION private: void reset_settings_value(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 42e404106..3500c48b5 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1175,10 +1175,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) { if (evt.data == 1) this->q->increase_instances(); else if (this->can_decrease_instances()) this->q->decrease_instances(); }); view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); }); view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this); -#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_ROTATED, [this](SimpleEvent&) { update(); }); view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_SCALED, [this](SimpleEvent&) { update(); }); -#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION view3D_canvas->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, [this](Event &evt) { this->sidebar->enable_buttons(evt.data); }); view3D_canvas->Bind(EVT_GLCANVAS_UPDATE_GEOMETRY, &priv::on_update_geometry, this); view3D_canvas->Bind(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, &priv::on_3dcanvas_mouse_dragging_finished, this); From 14fe55d4b83a3488c775371576407e45bf7848f4 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 29 Jan 2019 11:26:35 +0100 Subject: [PATCH 3/7] Fix of rotations using sidebar fields --- src/libslic3r/Geometry.cpp | 2 -- src/libslic3r/libslic3r.h | 6 ++++++ src/slic3r/GUI/GLCanvas3D.cpp | 6 +++--- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 18 +++++++++++++----- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index 58324893d..a9d3be539 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -1182,8 +1182,6 @@ Vec3d extract_euler_angles(const Eigen::Matrix& { #if ENABLE_NEW_EULER_ANGLES // reference: http://www.gregslabaugh.net/publications/euler.pdf - auto is_approx = [](double value, double test_value) -> bool { return std::abs(value - test_value) < EPSILON; }; - Vec3d angles1 = Vec3d::Zero(); Vec3d angles2 = Vec3d::Zero(); if (is_approx(std::abs(rotation_matrix(2, 0)), 1.0)) diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 19c6d3065..5fd2fafc1 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -164,6 +164,12 @@ static inline T lerp(const T& a, const T& b, Number t) return (Number(1) - t) * a + t * b; } +template +static inline bool is_approx(Number value, Number test_value) +{ + return std::abs(double(value) - double(test_value)) < double(EPSILON); +}; + } // namespace Slic3r #endif diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 107e763c6..3de7d67fa 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1820,7 +1820,7 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local) if (rot_axis_max != 2 && first_volume_idx != -1) { // Generic rotation, but no rotation around the Z axis. // Always do a local rotation (do not consider the selection to be a rigid body). - assert(rotation.z() == 0); + assert(is_approx(rotation.z(), 0.0)); const GLVolume &first_volume = *(*m_volumes)[first_volume_idx]; const Vec3d &rotation = first_volume.get_instance_rotation(); double z_diff = rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation()); @@ -1845,7 +1845,7 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local) else if (is_single_volume() || is_single_modifier()) { if (local) - volume.set_volume_rotation(rotation); + volume.set_volume_rotation(volume.get_volume_rotation() + rotation); else { Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); @@ -2262,7 +2262,7 @@ void GLCanvas3D::Selection::render_sidebar_hints(const std::string& sidebar_fiel } else if (is_single_volume() || is_single_modifier()) { - Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true) * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true); ::glTranslated(center(0), center(1), center(2)); ::glMultMatrixd(orient_matrix.data()); } diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index b4480f7e6..08829be93 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -345,16 +345,22 @@ void ObjectManipulation::update_if_dirty() m_cache.size = m_new_size; + Vec3d deg_rotation; + for (size_t i = 0; i < 3; ++i) + { + deg_rotation(i) = Geometry::rad2deg(m_new_rotation(i)); + } + if (m_cache.rotation(0) != m_new_rotation(0)) - m_og->set_value("rotation_x", double_to_string(Geometry::rad2deg(m_new_rotation(0)), 2)); + m_og->set_value("rotation_x", double_to_string(deg_rotation(0), 2)); if (m_cache.rotation(1) != m_new_rotation(1)) - m_og->set_value("rotation_y", double_to_string(Geometry::rad2deg(m_new_rotation(1)), 2)); + m_og->set_value("rotation_y", double_to_string(deg_rotation(1), 2)); if (m_cache.rotation(2) != m_new_rotation(2)) - m_og->set_value("rotation_z", double_to_string(Geometry::rad2deg(m_new_rotation(2)), 2)); + m_og->set_value("rotation_z", double_to_string(deg_rotation(2), 2)); - m_cache.rotation = m_new_rotation; + m_cache.rotation = deg_rotation; if (wxGetApp().plater()->canvas3D()->get_selection().requires_uniform_scale()) { m_lock_bnt->SetLock(true); @@ -400,10 +406,12 @@ void ObjectManipulation::change_rotation_value(const Vec3d& rotation) GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); const GLCanvas3D::Selection& selection = canvas->get_selection(); + Vec3d delta_rotation = rotation - m_cache.rotation; + Vec3d rad_rotation; for (size_t i = 0; i < 3; ++i) { - rad_rotation(i) = Geometry::deg2rad(rotation(i)); + rad_rotation(i) = Geometry::deg2rad(delta_rotation(i)); } canvas->get_selection().start_dragging(); From a09a9845b5c69daef8bff96ea7ebe9710181153d Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 29 Jan 2019 11:38:51 +0100 Subject: [PATCH 4/7] Fixed compile on OSX --- src/libslic3r/libslic3r.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 5fd2fafc1..54344c618 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -167,7 +167,7 @@ static inline T lerp(const T& a, const T& b, Number t) template static inline bool is_approx(Number value, Number test_value) { - return std::abs(double(value) - double(test_value)) < double(EPSILON); + return std::fabs(double(value) - double(test_value)) < double(EPSILON); }; } // namespace Slic3r From 39005cc8a059ceca1e69c0e47498cc8b4d87cab5 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 29 Jan 2019 12:09:40 +0100 Subject: [PATCH 5/7] Added missing include (build on OSX) --- src/libslic3r/libslic3r.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 54344c618..c7d9f7854 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "Technologies.hpp" From fd65489c11bc83fab1f6cdadad0e830e7c350b51 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 30 Jan 2019 12:18:01 +0100 Subject: [PATCH 6/7] Added debug output to test event handling sequence between Objects List and Object Manipulator fields --- src/slic3r/GUI/GUI_ObjectList.cpp | 3 +++ src/slic3r/GUI/GUI_ObjectManipulation.cpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index cb031a8d0..41a28d61b 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -66,6 +66,9 @@ ObjectList::ObjectList(wxWindow* parent) : // describe control behavior Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) { +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + std::cout << "SELECTION_CHANGED" << std::endl; +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ selection_changed(); #ifndef __WXMSW__ set_tooltip_for_item(get_mouse_position_in_control()); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 08829be93..86c9fda09 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -26,6 +26,10 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : // needed to hide the visual hints in 3D scene wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + std::cout << "KILL_FOCUS" << std::endl; +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + if (!m_cache.is_valid()) return; From 8076b39c4bc8af13c8c18e68695f0eb374169ef9 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 31 Jan 2019 14:12:07 +0100 Subject: [PATCH 7/7] Emulation of kill focus event on object manipulator fields when changing selection into objects list [WIN+LINUX] --- src/slic3r/GUI/GUI_ObjectList.cpp | 9 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 172 +++++++++++++--------- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 14 ++ 3 files changed, 121 insertions(+), 74 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index eb34e1251..9a789633f 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -66,9 +66,12 @@ ObjectList::ObjectList(wxWindow* parent) : // describe control behavior Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) { -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - std::cout << "SELECTION_CHANGED" << std::endl; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +#ifndef __APPLE__ + // On Windows and Linux, forces a kill focus emulation on the object manipulator fields because this event handler is called + // before the kill focus event handler on the object manipulator when changing selection in the list, invalidating the object + // manipulator cache with the following call to selection_changed() + wxGetApp().obj_manipul()->emulate_kill_focus(); +#endif // __APPLE__ selection_changed(); #ifndef __WXMSW__ set_tooltip_for_item(get_mouse_position_in_control()); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 86c9fda09..dc725bf88 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -17,85 +17,23 @@ namespace GUI ObjectManipulation::ObjectManipulation(wxWindow* parent) : OG_Settings(parent, true) +#ifndef __APPLE__ + , m_focused_option("") +#endif // __APPLE__ { m_og->set_name(_(L("Object Manipulation"))); m_og->label_width = 125; m_og->set_grid_vgap(5); - m_og->m_on_change = [this](const std::string& opt_key, const boost::any& value) { - // needed to hide the visual hints in 3D scene - wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); - -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - std::cout << "KILL_FOCUS" << std::endl; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ - - if (!m_cache.is_valid()) - return; - - std::vector axes{ "_x", "_y", "_z" }; - - std::string param; - std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); - - size_t i = 0; - Vec3d new_value; - for (auto axis : axes) - new_value(i++) = boost::any_cast(m_og->get_value(param+axis)); - - if (param == "position") - change_position_value(new_value); - else if (param == "rotation") - change_rotation_value(new_value); - else if (param == "scale") - change_scale_value(new_value); - else if (param == "size") - change_size_value(new_value); - }; - - m_og->m_fill_empty_value = [this](const std::string& opt_key) - { - // needed to hide the visual hints in 3D scene - wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); - - if (!m_cache.is_valid()) - return; - - std::string param; - std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); - - double value = 0.0; - - if (param == "position") { - int axis = opt_key.back() == 'x' ? 0 : - opt_key.back() == 'y' ? 1 : 2; - - value = m_cache.position(axis); - } - else if (param == "rotation") { - int axis = opt_key.back() == 'x' ? 0 : - opt_key.back() == 'y' ? 1 : 2; - - value = m_cache.rotation(axis); - } - else if (param == "scale") { - int axis = opt_key.back() == 'x' ? 0 : - opt_key.back() == 'y' ? 1 : 2; - - value = m_cache.scale(axis); - } - else if (param == "size") { - int axis = opt_key.back() == 'x' ? 0 : - opt_key.back() == 'y' ? 1 : 2; - - value = m_cache.size(axis); - } - - m_og->set_value(opt_key, double_to_string(value)); - }; + m_og->m_on_change = std::bind(&ObjectManipulation::on_change, this, std::placeholders::_1, std::placeholders::_2); + m_og->m_fill_empty_value = std::bind(&ObjectManipulation::on_fill_empty_value, this, std::placeholders::_1); m_og->m_set_focus = [this](const std::string& opt_key) { +#ifndef __APPLE__ + m_focused_option = opt_key; +#endif // __APPLE__ + // needed to show the visual hints in 3D scene wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, true); }; @@ -383,6 +321,23 @@ void ObjectManipulation::update_if_dirty() m_dirty = false; } +#ifndef __APPLE__ +void ObjectManipulation::emulate_kill_focus() +{ + if (m_focused_option.empty()) + return; + + // we need to use a copy because the value of m_focused_option is modified inside on_change() and on_fill_empty_value() + std::string option = m_focused_option; + + // see TextCtrl::propagate_value() + if (static_cast(m_og->get_fieldc(option, 0)->getWindow())->GetValue().empty()) + on_fill_empty_value(option); + else + on_change(option, 0); +} +#endif // __APPLE__ + void ObjectManipulation::reset_settings_value() { m_new_position = Vec3d::Zero(); @@ -504,5 +459,80 @@ void ObjectManipulation::change_size_value(const Vec3d& size) m_cache.size = size; } +void ObjectManipulation::on_change(const t_config_option_key& opt_key, const boost::any& value) +{ + // needed to hide the visual hints in 3D scene + wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); +#ifndef __APPLE__ + m_focused_option = ""; +#endif // __APPLE__ + + if (!m_cache.is_valid()) + return; + + std::vector axes{ "_x", "_y", "_z" }; + + std::string param; + std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); + + size_t i = 0; + Vec3d new_value; + for (auto axis : axes) + new_value(i++) = boost::any_cast(m_og->get_value(param + axis)); + + if (param == "position") + change_position_value(new_value); + else if (param == "rotation") + change_rotation_value(new_value); + else if (param == "scale") + change_scale_value(new_value); + else if (param == "size") + change_size_value(new_value); +} + +void ObjectManipulation::on_fill_empty_value(const std::string& opt_key) +{ + // needed to hide the visual hints in 3D scene + wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false); +#ifndef __APPLE__ + m_focused_option = ""; +#endif // __APPLE__ + + if (!m_cache.is_valid()) + return; + + std::string param; + std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param)); + + double value = 0.0; + + if (param == "position") { + int axis = opt_key.back() == 'x' ? 0 : + opt_key.back() == 'y' ? 1 : 2; + + value = m_cache.position(axis); + } + else if (param == "rotation") { + int axis = opt_key.back() == 'x' ? 0 : + opt_key.back() == 'y' ? 1 : 2; + + value = m_cache.rotation(axis); + } + else if (param == "scale") { + int axis = opt_key.back() == 'x' ? 0 : + opt_key.back() == 'y' ? 1 : 2; + + value = m_cache.scale(axis); + } + else if (param == "size") { + int axis = opt_key.back() == 'x' ? 0 : + opt_key.back() == 'y' ? 1 : 2; + + value = m_cache.size(axis); + } + + m_og->set_value(opt_key, double_to_string(value)); +} + } //namespace GUI } //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index b761beda8..16160c84d 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -77,6 +77,11 @@ class ObjectManipulation : public OG_Settings bool m_uniform_scale {true}; PrusaLockButton* m_lock_bnt{ nullptr }; +#ifndef __APPLE__ + // Currently focused option name (empty if none) + std::string m_focused_option; +#endif // __APPLE__ + public: ObjectManipulation(wxWindow* parent); ~ObjectManipulation() {} @@ -94,6 +99,12 @@ public: bool get_uniform_scaling() const { return m_uniform_scale; } void reset_cache() { m_cache.reset(); } +#ifndef __APPLE__ + // On Windows and Linux, emulates a kill focus event on the currently focused option (if any) + // Used only in ObjectList wxEVT_DATAVIEW_SELECTION_CHANGED handler which is called before the regular kill focus event + // bound to this class when changing selection in the objects list + void emulate_kill_focus(); +#endif // __APPLE__ private: void reset_settings_value(); @@ -108,6 +119,9 @@ private: void change_rotation_value(const Vec3d& rotation); void change_scale_value(const Vec3d& scale); void change_size_value(const Vec3d& size); + + void on_change(const t_config_option_key& opt_key, const boost::any& value); + void on_fill_empty_value(const std::string& opt_key); }; }}