diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4710132025..c948b351df 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3889,6 +3889,14 @@ void GLCanvas3D::do_flatten(const Vec3d& normal, const std::string& snapshot_typ do_rotate(""); // avoid taking another snapshot } +void GLCanvas3D::do_center() +{ + if (m_model == nullptr) + return; + + m_selection.center(); +} + void GLCanvas3D::do_mirror(const std::string& snapshot_type) { if (m_model == nullptr) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 186f96c22e..9dddcec17e 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -784,6 +784,7 @@ public: void do_rotate(const std::string& snapshot_type); void do_scale(const std::string& snapshot_type); void do_flatten(const Vec3d& normal, const std::string& snapshot_type); + void do_center(); void do_mirror(const std::string& snapshot_type); void update_gizmos_on_off_state(); diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index a8cd41fa93..11e434cf3e 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -892,6 +892,8 @@ void MenuFactory::create_bbl_object_menu() append_menu_item_fix_through_netfabb(&m_object_menu); // Object Simplify append_menu_item_simplify(&m_object_menu); + // Object Center + append_menu_item_center(&m_object_menu); // Object Split wxMenu* split_menu = new wxMenu(); if (!split_menu) @@ -983,6 +985,7 @@ void MenuFactory::create_bbl_part_menu() append_menu_item_delete(menu); append_menu_item_fix_through_netfabb(menu); append_menu_item_simplify(menu); + append_menu_item_center(menu); append_menu_items_mirror(menu); wxMenu* split_menu = new wxMenu(); if (!split_menu) @@ -1182,6 +1185,7 @@ wxMenu* MenuFactory::multi_selection_menu() append_menu_item_merge_to_multipart_object(menu); index++; } + append_menu_item_center(menu); append_menu_item_fix_through_netfabb(menu); //append_menu_item_simplify(menu); append_menu_item_delete(menu); @@ -1196,6 +1200,7 @@ wxMenu* MenuFactory::multi_selection_menu() append_menu_item_export_stl(menu, true); } else { + append_menu_item_center(menu); append_menu_item_fix_through_netfabb(menu); //append_menu_item_simplify(menu); append_menu_item_delete(menu); @@ -1279,6 +1284,25 @@ void MenuFactory::append_menu_item_simplify(wxMenu* menu) []() {return plater()->can_simplify(); }, m_parent); } +void MenuFactory::append_menu_item_center(wxMenu* menu) +{ + append_menu_item(menu, wxID_ANY, _L("Center") , "", + [this](wxCommandEvent&) { + plater()->center_selection(); + }, "", nullptr, + []() { + if (plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasView3D) + return false; + else { + Selection& selection = plater()->get_view3D_canvas3D()->get_selection(); + PartPlate* plate = plater()->get_partplate_list().get_selected_plate(); + Vec3d model_pos = selection.get_bounding_box().center(); + Vec3d center_pos = plate->get_center_origin(); + return !( (model_pos.x() == center_pos.x()) && (model_pos.y() == center_pos.y()) ); + } //disable if model is at center / not in View3D + }, m_parent); +} + void MenuFactory::append_menu_item_per_object_settings(wxMenu* menu) { const std::vector names = { _L("Edit in Parameter Table"), _L("Edit print parameters for a single object") }; diff --git a/src/slic3r/GUI/GUI_Factories.hpp b/src/slic3r/GUI/GUI_Factories.hpp index 6d4484e75e..1200729dd9 100644 --- a/src/slic3r/GUI/GUI_Factories.hpp +++ b/src/slic3r/GUI/GUI_Factories.hpp @@ -138,6 +138,7 @@ private: //BBS add bbl menu item void append_menu_item_clone(wxMenu* menu); void append_menu_item_simplify(wxMenu* menu); + void append_menu_item_center(wxMenu* menu); void append_menu_item_per_object_settings(wxMenu* menu); void append_menu_item_change_filament(wxMenu* menu); void append_menu_item_set_printable(wxMenu* menu); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index c0dae74de6..26b9f5104c 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -148,6 +148,12 @@ void View3D::delete_selected() m_canvas->delete_selected(); } +void View3D::center_selected() +{ + if (m_canvas != nullptr) + m_canvas->do_center(); +} + void View3D::mirror_selection(Axis axis) { if (m_canvas != nullptr) diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 8bd26bdc50..a61faf157f 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -63,6 +63,7 @@ public: void select_all(); void deselect_all(); void delete_selected(); + void center_selected(); void mirror_selection(Axis axis); bool is_dragging() const; diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 4f3fc0ce07..bfd1b11a55 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -1250,7 +1250,7 @@ Vec3d PartPlate::get_center_origin() Vec3d origin; origin(0) = (m_bounding_box.min(0) + m_bounding_box.max(0)) / 2;//m_origin.x() + m_width / 2; - origin(1) = (m_bounding_box.min(0) + m_bounding_box.max(0)) / 2; //m_origin.y() + m_depth / 2; + origin(1) = (m_bounding_box.min(1) + m_bounding_box.max(1)) / 2; //m_origin.y() + m_depth / 2; origin(2) = m_origin.z(); return origin; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 19d4270a55..fe0938ad84 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1676,6 +1676,7 @@ struct Plater::priv void delete_object_from_model(size_t obj_idx, bool refresh_immediately = true); //BBS void delete_all_objects_from_model(); void reset(bool apply_presets_change = false); + void center_selection(); void mirror(Axis axis); void split_object(); void split_volume(); @@ -3696,6 +3697,11 @@ void Plater::priv::reset(bool apply_presets_change) m_saved_timestamp = m_backup_timestamp = size_t(-1); } +void Plater::priv::center_selection() +{ + view3D->center_selected(); +} + void Plater::priv::mirror(Axis axis) { view3D->mirror_selection(axis); @@ -9456,6 +9462,7 @@ void Plater::suppress_background_process(const bool stop_background_process) this->p->suppressed_backround_processing_update = true; } +void Plater::center_selection() { p->center_selection(); } void Plater::mirror(Axis axis) { p->mirror(axis); } void Plater::split_object() { p->split_object(); } void Plater::split_volume() { p->split_volume(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 724520787c..2d24bae3a9 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -411,6 +411,7 @@ public: void paste_from_clipboard(); //BBS: add clone logic void clone_selection(); + void center_selection(); void search(bool plater_is_active, Preset::Type type, wxWindow *tag, wxTextCtrl *etag, wxWindow *stag); void mirror(Axis axis); void split_object(); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index c0abf6ba8c..b949bfd025 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -450,6 +450,20 @@ void Selection::clone(int numbers) } } +void Selection::center() +{ + PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_selected_plate(); + + // calc distance + Vec3d src_pos = this->get_bounding_box().center(); + Vec3d tar_pos = plate->get_center_origin(); + Vec3d distance = Vec3d(tar_pos.x() - src_pos.x(), tar_pos.y() - src_pos.y(), 0); + + this->move_to_center(distance); + wxGetApp().plater()->get_view3D_canvas3D()->do_move(L("Move Object")); + return; +} + //BBS void Selection::set_printable(bool printable) { @@ -806,6 +820,39 @@ void Selection::start_dragging() set_caches(); } +void Selection::move_to_center(const Vec3d& displacement, bool local) +{ + if (!m_valid) + return; + + EMode translation_type = m_mode; + //BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": %1%, displacement {%2%, %3%, %4%}") % __LINE__ % displacement(X) % displacement(Y) % displacement(Z); + + set_caches(); + for (unsigned int i : m_list) { + GLVolume& v = *(*m_volumes)[i]; + if (m_mode == Volume) { + if (local) + v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + displacement); + else { + const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement; + v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement); + } + } + else if (m_mode == Instance) { + if (is_from_fully_selected_instance(i)) { + v.set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement); + } + else { + const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement; + v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement); + translation_type = Volume; + } + } + } + this->set_bounding_boxes_dirty(); +} + void Selection::translate(const Vec3d& displacement, bool local) { if (!m_valid) diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 96a98e5ab5..5c1669b1b9 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -262,6 +262,7 @@ public: void add_curr_plate(); void remove_curr_plate(); void clone(int numbers = 1); + void center(); void set_printable(bool printable); void add_all(); @@ -330,6 +331,7 @@ public: bool is_dragging() const { return m_dragging; } void translate(const Vec3d& displacement, bool local = false); + void move_to_center(const Vec3d& displacement, bool local = false); void rotate(const Vec3d& rotation, TransformationType transformation_type); void flattening_rotate(const Vec3d& normal); void scale(const Vec3d& scale, TransformationType transformation_type);