diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 5d286846b4..34b5f4067b 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -118,17 +118,17 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection) if (needs_reset) clear(); - if (volume->is_modifier) - m_mode = Volume; - else if (!contains_volume(volume_idx)) - m_mode = Instance; - // else -> keep current mode + if (!contains_volume(volume_idx)) + m_mode = volume->is_modifier ? Volume : Instance; + else + // keep current mode + return; switch (m_mode) { case Volume: { - if (volume->volume_idx() >= 0 && (is_empty() || (volume->instance_idx() == get_instance_idx()))) + if ((volume->volume_idx() >= 0) && (is_empty() || (volume->instance_idx() == get_instance_idx()))) _add_volume(volume_idx); break; @@ -439,6 +439,8 @@ void Selection::translate(const Vec3d& displacement, bool local) if (!m_valid) return; + EMode translation_type = m_mode; + for (unsigned int i : m_list) { if ((m_mode == Volume) || (*m_volumes)[i]->is_wipe_tower) @@ -452,13 +454,22 @@ void Selection::translate(const Vec3d& displacement, bool local) } } else if (m_mode == Instance) - (*m_volumes)[i]->set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement); + { + if (_is_from_fully_selected_instance(i)) + (*m_volumes)[i]->set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement); + else + { + 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; + (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement); + translation_type = Volume; + } + } } #if !DISABLE_INSTANCES_SYNCH - if (m_mode == Instance) + if (translation_type == Instance) _synchronize_unselected_instances(SYNC_ROTATION_NONE); - else if (m_mode == Volume) + else if (translation_type == Volume) _synchronize_unselected_volumes(); #endif // !DISABLE_INSTANCES_SYNCH @@ -1683,5 +1694,29 @@ void Selection::_ensure_on_bed() } } +bool Selection::_is_from_fully_selected_instance(unsigned int volume_idx) const +{ + struct SameInstance + { + int obj_idx; + int inst_idx; + GLVolumePtrs& volumes; + + SameInstance(int obj_idx, int inst_idx, GLVolumePtrs& volumes) : obj_idx(obj_idx), inst_idx(inst_idx), volumes(volumes) {} + bool operator () (unsigned int i) { return (volumes[i]->object_idx() == obj_idx) && (volumes[i]->instance_idx() == inst_idx); } + }; + + if ((unsigned int)m_volumes->size() <= volume_idx) + return false; + + GLVolume* volume = (*m_volumes)[volume_idx]; + int object_idx = volume->object_idx(); + if ((int)m_model->objects.size() <= object_idx) + return false; + + unsigned int count = (unsigned int)std::count_if(m_list.begin(), m_list.end(), SameInstance(object_idx, volume->instance_idx(), *m_volumes)); + return count == (unsigned int)m_model->objects[object_idx]->volumes.size(); +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 200f239c1f..4b2a72d7c0 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -297,6 +297,7 @@ private: void _synchronize_unselected_instances(SyncRotationType sync_rotation_type); void _synchronize_unselected_volumes(); void _ensure_on_bed(); + bool _is_from_fully_selected_instance(unsigned int volume_idx) const; }; } // namespace GUI