diff --git a/resources/icons/shape_ungroup_o.png b/resources/icons/shape_ungroup_o.png new file mode 100644 index 000000000..97746d32c Binary files /dev/null and b/resources/icons/shape_ungroup_o.png differ diff --git a/resources/icons/shape_ungroup_p.png b/resources/icons/shape_ungroup_p.png new file mode 100644 index 000000000..81c0198ff Binary files /dev/null and b/resources/icons/shape_ungroup_p.png differ diff --git a/resources/icons/support_blocker_.png b/resources/icons/support_blocker_.png index 0873c5e6e..fc658e4f6 100644 Binary files a/resources/icons/support_blocker_.png and b/resources/icons/support_blocker_.png differ diff --git a/resources/icons/support_enforcer_.png b/resources/icons/support_enforcer_.png index 265cebcb9..ac34b6cb0 100644 Binary files a/resources/icons/support_enforcer_.png and b/resources/icons/support_enforcer_.png differ diff --git a/resources/icons/toolbar.png b/resources/icons/toolbar.png index 79246bcf9..660be1a5d 100644 Binary files a/resources/icons/toolbar.png and b/resources/icons/toolbar.png differ diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index d792a3bbe..0c13bdd47 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1863,6 +1863,19 @@ void GLCanvas3D::Selection::_update_type() else if ((selected_instances_count > 1) && (selected_instances_count * volumes_count == (unsigned int)m_list.size())) m_type = MultipleFullInstance; } + else + { + int sels_cntr = 0; + for (ObjectIdxsToInstanceIdxsMap::iterator it = m_cache.content.begin(); it != m_cache.content.end(); ++it) + { + const ModelObject* model_object = m_model->objects[it->first]; + unsigned int volumes_count = (unsigned int)model_object->volumes.size(); + unsigned int instances_count = (unsigned int)model_object->instances.size(); + sels_cntr += volumes_count * instances_count; + } + if (sels_cntr == (unsigned int)m_list.size()) + m_type = MultipleFullObject; + } } } @@ -1915,6 +1928,11 @@ void GLCanvas3D::Selection::_update_type() std::cout << "selection type: SingleFullObject" << std::endl; break; } + case MultipleFullObject: + { + std::cout << "selection type: MultipleFullObject" << std::endl; + break; + } case SingleFullInstance: { std::cout << "selection type: SingleFullInstance" << std::endl; @@ -4536,7 +4554,7 @@ bool GLCanvas3D::_init_toolbar() item.name = "splitvolumes"; item.tooltip = GUI::L_str("Split to parts"); - item.sprite_id = 6; + item.sprite_id = 11; item.is_toggable = false; item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES; if (!m_toolbar.add_item(item)) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 1a377e792..a48f2217f 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -378,6 +378,7 @@ public: SingleVolume, MultipleVolume, SingleFullObject, + MultipleFullObject, SingleFullInstance, MultipleFullInstance, Mixed @@ -491,6 +492,7 @@ public: bool is_single_full_instance() const; bool is_multiple_full_instance() const { return m_type == MultipleFullInstance; } bool is_single_full_object() const { return m_type == SingleFullObject; } + bool is_multiple_full_object() const { return m_type == MultipleFullObject; } bool is_single_volume() const { return m_type == SingleVolume; } bool is_multiple_volume() const { return m_type == MultipleVolume; } bool is_mixed() const { return m_type == Mixed; } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 32742b490..6cfd88e00 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -324,7 +324,7 @@ void ObjectList::key_event(wxKeyEvent& event) remove(); } else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL)) - select_all(); + select_item_all_children(); else event.Skip(); } @@ -996,51 +996,60 @@ void ObjectList::parts_changed(int obj_idx) void ObjectList::part_selection_changed() { - auto item = GetSelection(); int obj_idx = -1; ConfigOptionsGroup* og = wxGetApp().obj_manipul()->get_og(); m_config = nullptr; wxString object_name = wxEmptyString; - if (item) + + if (multiple_selection()) + og->set_name(" " + _(L("Group manipulation")) + " "); + else { - const bool is_settings_item = m_objects_model->IsSettingsItem(item); - bool is_part = false; - wxString og_name = wxEmptyString; - if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { - obj_idx = m_objects_model->GetIdByItem(item); - og_name = _(L("Object manipulation")); - m_config = &(*m_objects)[obj_idx]->config; - } - else { - auto parent = m_objects_model->GetParent(item); - // Take ID of the parent object to "inform" perl-side which object have to be selected on the scene - obj_idx = m_objects_model->GetIdByItem(parent); - if (is_settings_item) { - if (m_objects_model->GetParent(parent) == wxDataViewItem(0)) { - og_name = _(L("Object Settings to modify")); - m_config = &(*m_objects)[obj_idx]->config; + const auto item = GetSelection(); + if (item) + { + const bool is_settings_item = m_objects_model->IsSettingsItem(item); + bool is_part = false; + wxString og_name = wxEmptyString; + if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { + obj_idx = m_objects_model->GetIdByItem(item); + og_name = _(L("Object manipulation")); + m_config = &(*m_objects)[obj_idx]->config; + } + else { + auto parent = m_objects_model->GetParent(item); + // Take ID of the parent object to "inform" perl-side which object have to be selected on the scene + obj_idx = m_objects_model->GetIdByItem(parent); + if (is_settings_item) { + if (m_objects_model->GetParent(parent) == wxDataViewItem(0)) { + og_name = _(L("Object Settings to modify")); + m_config = &(*m_objects)[obj_idx]->config; + } + else { + og_name = _(L("Part Settings to modify")); + is_part = true; + auto main_parent = m_objects_model->GetParent(parent); + obj_idx = m_objects_model->GetIdByItem(main_parent); + const auto volume_id = m_objects_model->GetVolumeIdByItem(parent); + m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; + } } - else { - og_name = _(L("Part Settings to modify")); + else if (m_objects_model->GetItemType(item) == itVolume) { + og_name = _(L("Part manipulation")); is_part = true; - auto main_parent = m_objects_model->GetParent(parent); - obj_idx = m_objects_model->GetIdByItem(main_parent); - const auto volume_id = m_objects_model->GetVolumeIdByItem(parent); + const auto volume_id = m_objects_model->GetVolumeIdByItem(item); m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; } + else if (m_objects_model->GetItemType(item) == itInstance) { + og_name = _(L("Instance manipulation")); + } } - else if (m_objects_model->GetItemType(item) == itVolume) { - og_name = _(L("Part manipulation")); - is_part = true; - const auto volume_id = m_objects_model->GetVolumeIdByItem(item); - m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; - } - } - og->set_name(" " + og_name + " "); - object_name = m_objects_model->GetName(item); - if (m_default_config) delete m_default_config; - m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(is_part)); + og->set_name(" " + og_name + " "); + object_name = m_objects_model->GetName(item); + if (m_default_config) delete m_default_config; + m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(is_part)); + } } og->set_value("object_name", object_name); @@ -1209,13 +1218,20 @@ void ObjectList::update_selections() auto& selection = _3DScene::get_canvas(wxGetApp().canvas3D())->get_selection(); wxDataViewItemArray sels; - if (selection.is_single_full_object()) { + if (selection.is_single_full_object()) + { + sels.Add(m_objects_model->GetItemById(selection.get_object_idx())); + } + else if (selection.is_single_volume() || selection.is_multiple_volume() || selection.is_multiple_full_object()) { for (auto idx : selection.get_volume_idxs()) { const auto gl_vol = selection.get_volume(idx); - sels.Add(m_objects_model->GetItemByVolumeId(gl_vol->object_idx(), gl_vol->volume_idx())); + if (selection.is_multiple_full_object()) + sels.Add(m_objects_model->GetItemById(gl_vol->object_idx())); + else + sels.Add(m_objects_model->GetItemByVolumeId(gl_vol->object_idx(), gl_vol->volume_idx())); } } - else if (selection.is_single_full_instance()) { + else if (selection.is_single_full_instance() || selection.is_multiple_full_instance()) { for (auto idx : selection.get_instance_idxs()) { sels.Add(m_objects_model->GetItemByInstanceId(selection.get_object_idx(), idx)); } @@ -1303,6 +1319,27 @@ void ObjectList::select_all() selection_changed(); } +void ObjectList::select_item_all_children() +{ + wxDataViewItemArray sels; + + // There is no selection before OR some object is selected => select all objects + if (!GetSelection() || m_objects_model->GetItemType(GetSelection()) == itObject) { + for (int i = 0; i < m_objects->size(); i++) + sels.Add(m_objects_model->GetItemById(i)); + } + else { + const auto item = GetSelection(); + // Some volume(instance) is selected => select all volumes(instances) inside the current object + if (m_objects_model->GetItemType(item) & (itVolume | itInstance)) { + m_objects_model->GetChildren(m_objects_model->GetParent(item), sels); + } + } + + SetSelections(sels); + selection_changed(); +} + void ObjectList::fix_multiselection_conflicts() { if (GetSelectedItemsCount() <= 1) @@ -1314,7 +1351,7 @@ void ObjectList::fix_multiselection_conflicts() GetSelections(sels); for (auto item : sels) { - if (m_objects_model->IsSettingsItem(item)) + if (m_objects_model->GetItemType(item) & (itSettings|itInstanceRoot)) Unselect(item); else if (m_objects_model->GetParent(item) != wxDataViewItem(0)) Unselect(m_objects_model->GetParent(item)); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 33b2a7608..d5f4848ad 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -143,6 +143,7 @@ public: void select_item(const wxDataViewItem& item); void select_items(const wxDataViewItemArray& sels); void select_all(); + void select_item_all_children(); // correct current selections to avoid of the possible conflicts void fix_multiselection_conflicts(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 84a32427e..a1db54b0d 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1839,9 +1839,9 @@ bool Plater::priv::init_object_menu() return false; wxMenuItem* item_split_objects = append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")), - [this](wxCommandEvent&) { split_object(); }, "shape_ungroup.png", &object_menu); + [this](wxCommandEvent&) { split_object(); }, "shape_ungroup_o.png", &object_menu); wxMenuItem* item_split_volumes = append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")), - [this](wxCommandEvent&) { split_volume(); }, "shape_ungroup.png", &object_menu); + [this](wxCommandEvent&) { split_volume(); }, "shape_ungroup_p.png", &object_menu); wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "shape_ungroup.png");