diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 427c0e99fc..677653a7d3 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3746,12 +3746,22 @@ void GLCanvas3D::do_reset_skew(const std::string& snapshot_type) if (!snapshot_type.empty()) wxGetApp().plater()->take_snapshot(_(snapshot_type)); + // stores current min_z of instances + std::map, double> min_zs; + if (!snapshot_type.empty()) { + for (int i = 0; i < static_cast(m_model->objects.size()); ++i) { + const ModelObject* obj = m_model->objects[i]; + for (int j = 0; j < static_cast(obj->instances.size()); ++j) { + min_zs[{ i, j }] = obj->instance_bounding_box(j).min.z(); + } + } + } + std::set> done; // keeps track of modified instances - const Selection::IndicesList& idxs = m_selection.get_volume_idxs(); + Selection::EMode selection_mode = m_selection.get_mode(); - for (unsigned int id : idxs) { - const GLVolume* v = m_volumes.volumes[id]; + for (const GLVolume* v : m_volumes.volumes) { int object_idx = v->object_idx(); if (object_idx < 0 || (int)m_model->objects.size() <= object_idx) continue; @@ -3761,14 +3771,30 @@ void GLCanvas3D::do_reset_skew(const std::string& snapshot_type) done.insert(std::pair(object_idx, instance_idx)); + // Mirror instances/volumes ModelObject* model_object = m_model->objects[object_idx]; if (model_object != nullptr) { - model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation()); - model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation()); + if (selection_mode == Selection::Instance) + model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation()); + else if (selection_mode == Selection::Volume) + model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation()); model_object->invalidate_bounding_box(); } } + // Fixes sinking/flying instances + for (const std::pair& i : done) { + ModelObject* m = m_model->objects[i.first]; + double shift_z = m->get_instance_min_z(i.second); + // leave sinking instances as sinking + if (min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) { + Vec3d shift(0.0, 0.0, -shift_z); + m_selection.translate(i.first, i.second, shift); + m->translate_instance(i.second, shift); + } + wxGetApp().obj_list()->update_info_items(static_cast(i.first)); + } + post_event(SimpleEvent(EVT_GLCANVAS_RESET_SKEW)); m_dirty = true; diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 6d4c916f19..531b2a8ce1 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -506,6 +506,10 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : else return; + // Synchronize instances/volumes. + selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL); + selection.synchronize_unselected_volumes(); + canvas->do_scale(L("Reset scale")); UpdateAndShow(true); #else diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index e4f59dcc7d..4a5ddb59c9 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1543,6 +1543,15 @@ void Selection::reset_skew() } } +#if !DISABLE_INSTANCES_SYNCH + if (m_mode == Instance) + // even if there is no rotation, we pass SyncRotationType::GENERAL to force + // synchronize_unselected_instances() to remove skew from the other instances + synchronize_unselected_instances(SyncRotationType::GENERAL); + else if (m_mode == Volume) + synchronize_unselected_volumes(); +#endif // !DISABLE_INSTANCES_SYNCH + ensure_on_bed(); set_bounding_boxes_dirty(); wxGetApp().plater()->canvas3D()->requires_check_outside_state();