diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index b9e1f5195c..4fd65ea77f 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1526,8 +1526,7 @@ void GLCanvas3D::Selection::flattening_rotate(const Vec3d& normal) m_bounding_box_dirty = true; } - -void GLCanvas3D::Selection::scale(const Vec3d& scale) +void GLCanvas3D::Selection::scale(const Vec3d& scale, bool local) { if (!m_valid) return; @@ -1553,7 +1552,9 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale) Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3); // extracts scaling factors from the composed transformation Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm()); - (*m_volumes)[i]->set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center)); + if (!local) + (*m_volumes)[i]->set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center)); + (*m_volumes)[i]->set_instance_scaling_factor(new_scale); } else if (m_mode == Volume) @@ -1561,7 +1562,12 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale) Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3); // extracts scaling factors from the composed transformation Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm()); - (*m_volumes)[i]->set_volume_offset(m * m_cache.volumes_data[i].get_volume_position()); + if (!local) + { + Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center); + std::cout << to_string(offset) << std::endl; + (*m_volumes)[i]->set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset); + } (*m_volumes)[i]->set_volume_scaling_factor(new_scale); } #else @@ -2251,16 +2257,31 @@ void GLCanvas3D::Selection::_synchronize_unselected_volumes() #if ENABLE_ENSURE_ON_BED_WHILE_SCALING void GLCanvas3D::Selection::_ensure_on_bed() { + typedef std::map, double> InstancesToZMap; + InstancesToZMap instances_min_z; + for (unsigned int i : m_list) { GLVolume* volume = (*m_volumes)[i]; if (!volume->is_modifier) { double min_z = volume->transformed_convex_hull_bounding_box().min(2); - if (min_z != 0.0) - volume->set_instance_offset(Z, volume->get_instance_offset(Z) - min_z); + std::pair instance = std::make_pair(volume->object_idx(), volume->instance_idx()); + InstancesToZMap::iterator it = instances_min_z.find(instance); + if (it == instances_min_z.end()) + it = instances_min_z.insert(InstancesToZMap::value_type(instance, DBL_MAX)).first; + + it->second = std::min(it->second, min_z); } } + + for (GLVolume* volume : *m_volumes) + { + std::pair instance = std::make_pair(volume->object_idx(), volume->instance_idx()); + InstancesToZMap::iterator it = instances_min_z.find(instance); + if (it != instances_min_z.end()) + volume->set_instance_offset(Z, volume->get_instance_offset(Z) - it->second); + } } #endif // ENABLE_ENSURE_ON_BED_WHILE_SCALING @@ -4040,7 +4061,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { case Gizmos::Scale: { - m_selection.scale(m_gizmos.get_scale()); + m_selection.scale(m_gizmos.get_scale(), false); _on_scale(); wxGetApp().obj_manipul()->update_settings_value(m_selection); m_dirty = true; @@ -4251,7 +4272,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { // Apply new temporary scale factors - m_selection.scale(m_gizmos.get_scale()); + m_selection.scale(m_gizmos.get_scale(), evt.AltDown()); wxGetApp().obj_manipul()->update_settings_value(m_selection); break; } @@ -6482,6 +6503,7 @@ void GLCanvas3D::_on_scale() } else if (selection_mode == Selection::Volume) { + model_object->instances[instance_idx]->set_offset(v->get_instance_offset()); model_object->volumes[volume_idx]->set_scaling_factor(v->get_volume_scaling_factor()); model_object->volumes[volume_idx]->set_offset(v->get_volume_offset()); } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 66747cf1e7..d74fee7643 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -519,7 +519,7 @@ public: void translate(const Vec3d& displacement); void rotate(const Vec3d& rotation, bool local); void flattening_rotate(const Vec3d& normal); - void scale(const Vec3d& scale); + void scale(const Vec3d& scale, bool local); void mirror(Axis axis); void translate(unsigned int object_idx, const Vec3d& displacement); diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 3f7dc6cacf..7b94798eed 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -787,13 +787,14 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); for (unsigned int idx : idxs) { - box.merge(selection.get_volume(idx)->bounding_box); + const GLVolume* vol = selection.get_volume(idx); + box.merge(vol->bounding_box.transformed(vol->get_volume_transformation().get_matrix())); } // gets transform from first selected volume const GLVolume* v = selection.get_volume(*idxs.begin()); #if ENABLE_MODELVOLUME_TRANSFORM - transform = v->world_matrix(); + transform = v->get_instance_transformation().get_matrix(); // gets angles from first selected volume angles = v->get_instance_rotation(); // consider rotation+mirror only components of the transform for offsets diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 6418b2e8ba..6cfa62a8ac 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -436,7 +436,7 @@ void ObjectManipulation::change_scale_value(const Vec3d& scale) auto canvas = _3DScene::get_canvas(wxGetApp().canvas3D()); canvas->get_selection().start_dragging(); - canvas->get_selection().scale(scaling_factor); + canvas->get_selection().scale(scaling_factor, false); canvas->_on_scale(); }