diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 2df47519c..86ec79da8 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1409,19 +1409,46 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation) Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); - bool single_full_instance = is_single_full_instance(); - for (unsigned int i : m_list) { - if (single_full_instance) + if (is_single_full_instance()) (*m_volumes)[i]->set_rotation(rotation); else { - Eigen::Matrix new_rotation_matrix = (m * m_cache.volumes_data[i].get_rotation_matrix()).matrix().block(0, 0, 3, 3); - Vec3d angles = Geometry::extract_euler_angles(new_rotation_matrix); + Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_rotation_matrix()).matrix().block(0, 0, 3, 3); + Vec3d new_rotation = Geometry::extract_euler_angles(new_matrix); (*m_volumes)[i]->set_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_position() - m_cache.dragging_center)); - (*m_volumes)[i]->set_rotation(Vec3d(angles(0), angles(1), angles(2))); + (*m_volumes)[i]->set_rotation(new_rotation); + } + } + + if (m_mode == Instance) + _synchronize_unselected_instances(); + + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::scale(const Vec3d& scale) +{ + if (!m_valid) + return; + + Transform3d m = Transform3d::Identity(); + m.scale(scale); + + for (unsigned int i : m_list) + { + if (is_single_full_instance()) + (*m_volumes)[i]->set_scaling_factor(scale); + else + { + Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_rotation_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_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_position() - m_cache.dragging_center)); + (*m_volumes)[i]->set_scaling_factor(new_scale); } } @@ -2652,8 +2679,8 @@ wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); -wxDEFINE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); #if !ENABLE_EXTENDED_SELECTION +wxDEFINE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); wxDEFINE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); #endif // !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); @@ -3209,6 +3236,11 @@ void GLCanvas3D::update_gizmos_data() #if ENABLE_EXTENDED_SELECTION bool enable_move_z = !m_selection.is_wipe_tower(); m_gizmos.enable_grabber(Gizmos::Move, 2, enable_move_z); + bool enable_scale_xyz = m_selection.is_single_full_instance(); + for (int i = 0; i < 6; ++i) + { + m_gizmos.enable_grabber(Gizmos::Scale, i, enable_scale_xyz); + } if (m_selection.is_single_full_instance()) { @@ -3791,11 +3823,21 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#if ENABLE_EXTENDED_SELECTION + m_regenerate_volumes = false; + m_selection.scale(m_gizmos.get_scale()); + _on_scale(); +#else post_event(Vec3dEvent(EVT_GIZMO_SCALE, m_gizmos.get_scale())); +#endif // ENABLE_EXTENDED_SELECTION #else m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#if ENABLE_EXTENDED_SELECTION + wxGetApp().obj_manipul()->update_settings_value(m_selection); +#else wxGetApp().obj_manipul()->update_scale_values(); +#endif // ENABLE_EXTENDED_SELECTION m_dirty = true; break; } @@ -3804,8 +3846,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_EXTENDED_SELECTION m_regenerate_volumes = false; - const Vec3d& rotation = m_gizmos.get_rotation(); - m_selection.rotate(rotation); + m_selection.rotate(m_gizmos.get_rotation()); _on_rotate(); #else post_event(Vec3dEvent(EVT_GIZMO_ROTATE, std::move(m_gizmos.get_rotation()))); @@ -4135,15 +4176,17 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -#if ENABLE_EXTENDED_SELECTION -#else // Apply new temporary scale factors +#if ENABLE_EXTENDED_SELECTION + m_selection.scale(m_gizmos.get_scale()); + wxGetApp().obj_manipul()->update_settings_value(m_selection); +#else const Vec3d& scale = m_gizmos.get_scale(); for (GLVolume* v : volumes) { v->set_scaling_factor(scale); } - wxGetApp().obj_manipul()->update_scale_values(scale); + wxGetApp().obj_manipul()->update_scale_value(scale); #endif // ENABLE_EXTENDED_SELECTION #else // Apply new temporary scale factor @@ -4159,6 +4202,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Rotate: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + // Apply new temporary rotations #if ENABLE_EXTENDED_SELECTION m_selection.rotate(m_gizmos.get_rotation()); wxGetApp().obj_manipul()->update_settings_value(m_selection); @@ -4345,7 +4389,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - post_event(Vec3dEvent(EVT_GIZMO_SCALE, m_gizmos.get_scale())); +#if ENABLE_EXTENDED_SELECTION + m_regenerate_volumes = false; + _on_scale(); +#endif // ENABLE_EXTENDED_SELECTION #else m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM @@ -6473,6 +6520,42 @@ void GLCanvas3D::_on_rotate() // schedule_background_process } + +void GLCanvas3D::_on_scale() +{ + if (m_model == nullptr) + return; + + std::set> done; // prevent scaling instances twice + const Selection::IndicesList& selection = m_selection.get_volume_idxs(); + + for (unsigned int i : selection) + { + const GLVolume* v = m_volumes.volumes[i]; + int object_idx = v->object_idx(); + if (object_idx >= 1000) + continue; + + int instance_idx = v->instance_idx(); + + // prevent rotating instances twice + std::pair done_id(object_idx, instance_idx); + if (done.find(done_id) != done.end()) + continue; + + done.insert(done_id); + + // Rotate instances. + ModelObject* model_object = m_model->objects[object_idx]; + if (model_object != nullptr) + { + model_object->instances[instance_idx]->set_scaling_factor(v->get_scaling_factor()); + model_object->invalidate_bounding_box(); + } + } + + // schedule_background_process +} #else void GLCanvas3D::_on_move(const std::vector& volume_idxs) { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d556ea54d..828e24fa6 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -115,8 +115,8 @@ wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); -wxDECLARE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); #if !ENABLE_EXTENDED_SELECTION +wxDECLARE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); wxDECLARE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); #endif // !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); @@ -491,6 +491,7 @@ public: void translate(const Vec3d& displacement); void rotate(const Vec3d& rotation); + void scale(const Vec3d& scale); void render(bool show_indirect_selection) const; @@ -939,6 +940,7 @@ private: #if ENABLE_EXTENDED_SELECTION void _on_move(); void _on_rotate(); + void _on_scale(); #else void _on_move(const std::vector& volume_idxs); #endif // ENABLE_EXTENDED_SELECTION diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 5eb90054c..6eff84d92 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -274,6 +274,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); update_position_value(volume->get_offset()); update_rotation_value(volume->get_rotation()); + update_scale_value(volume->get_scaling_factor()); m_og->enable(); } else @@ -285,6 +286,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); update_position_value(volume->get_offset()); update_rotation_value(volume->get_rotation()); + update_scale_value(volume->get_scaling_factor()); m_og->enable(); } else if (selection.is_wipe_tower()) @@ -293,6 +295,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); update_position_value(volume->get_offset()); update_rotation_value(volume->get_rotation()); + update_scale_value(volume->get_scaling_factor()); m_og->enable(); } else if (selection.is_modifier()) @@ -301,6 +304,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); update_position_value(volume->get_offset()); update_rotation_value(volume->get_rotation()); + update_scale_value(volume->get_scaling_factor()); m_og->enable(); } else @@ -420,7 +424,7 @@ void ObjectManipulation::update_position_value(const Vec3d& position) } #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -void ObjectManipulation::update_scale_values(const Vec3d& scaling_factor) +void ObjectManipulation::update_scale_value(const Vec3d& scaling_factor) { // this is temporary // to be able to update the values as size diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 7cd5fce27..c0cd70160 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -62,7 +62,7 @@ public: // update scale values after scale unit changing or "gizmos" void update_scale_values(); #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - void update_scale_values(const Vec3d& scaling_factor); + void update_scale_value(const Vec3d& scaling_factor); #else void update_scale_values(double scaling_factor); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM