Merge remote-tracking branch 'origin/dev_native' into tm_sla_supports_backend
							
								
								
									
										
											BIN
										
									
								
								resources/icons/shape_ungroup_o.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/shape_ungroup_p.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.2 KiB | 
| Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.8 KiB | 
| Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB | 
| Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 33 KiB | 
|  | @ -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())) |                 else if ((selected_instances_count > 1) && (selected_instances_count * volumes_count == (unsigned int)m_list.size())) | ||||||
|                     m_type = MultipleFullInstance; |                     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; |         std::cout << "selection type: SingleFullObject" << std::endl; | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  |     case MultipleFullObject: | ||||||
|  |     { | ||||||
|  |         std::cout << "selection type: MultipleFullObject" << std::endl; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|     case SingleFullInstance: |     case SingleFullInstance: | ||||||
|     { |     { | ||||||
|         std::cout << "selection type: SingleFullInstance" << std::endl; |         std::cout << "selection type: SingleFullInstance" << std::endl; | ||||||
|  | @ -4536,7 +4554,7 @@ bool GLCanvas3D::_init_toolbar() | ||||||
| 
 | 
 | ||||||
|     item.name = "splitvolumes"; |     item.name = "splitvolumes"; | ||||||
|     item.tooltip = GUI::L_str("Split to parts"); |     item.tooltip = GUI::L_str("Split to parts"); | ||||||
|     item.sprite_id = 6; |     item.sprite_id = 11; | ||||||
|     item.is_toggable = false; |     item.is_toggable = false; | ||||||
|     item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES; |     item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES; | ||||||
|     if (!m_toolbar.add_item(item)) |     if (!m_toolbar.add_item(item)) | ||||||
|  |  | ||||||
|  | @ -378,6 +378,7 @@ public: | ||||||
|             SingleVolume, |             SingleVolume, | ||||||
|             MultipleVolume, |             MultipleVolume, | ||||||
|             SingleFullObject, |             SingleFullObject, | ||||||
|  |             MultipleFullObject, | ||||||
|             SingleFullInstance, |             SingleFullInstance, | ||||||
|             MultipleFullInstance, |             MultipleFullInstance, | ||||||
|             Mixed |             Mixed | ||||||
|  | @ -491,6 +492,7 @@ public: | ||||||
|         bool is_single_full_instance() const; |         bool is_single_full_instance() const; | ||||||
|         bool is_multiple_full_instance() const { return m_type == MultipleFullInstance; } |         bool is_multiple_full_instance() const { return m_type == MultipleFullInstance; } | ||||||
|         bool is_single_full_object() const { return m_type == SingleFullObject; } |         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_single_volume() const { return m_type == SingleVolume; } | ||||||
|         bool is_multiple_volume() const { return m_type == MultipleVolume; } |         bool is_multiple_volume() const { return m_type == MultipleVolume; } | ||||||
|         bool is_mixed() const { return m_type == Mixed; } |         bool is_mixed() const { return m_type == Mixed; } | ||||||
|  |  | ||||||
|  | @ -324,7 +324,7 @@ void ObjectList::key_event(wxKeyEvent& event) | ||||||
|         remove(); |         remove(); | ||||||
|     } |     } | ||||||
|     else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL)) |     else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL)) | ||||||
|         select_all(); |         select_item_all_children(); | ||||||
|     else |     else | ||||||
|         event.Skip(); |         event.Skip(); | ||||||
| } | } | ||||||
|  | @ -996,51 +996,60 @@ void ObjectList::parts_changed(int obj_idx) | ||||||
| 
 | 
 | ||||||
| void ObjectList::part_selection_changed() | void ObjectList::part_selection_changed() | ||||||
| { | { | ||||||
|     auto item = GetSelection(); |  | ||||||
|     int obj_idx = -1; |     int obj_idx = -1; | ||||||
|     ConfigOptionsGroup* og = wxGetApp().obj_manipul()->get_og(); |     ConfigOptionsGroup* og = wxGetApp().obj_manipul()->get_og(); | ||||||
|     m_config = nullptr; |     m_config = nullptr; | ||||||
|     wxString object_name = wxEmptyString; |     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); |         const auto item = GetSelection(); | ||||||
|         bool is_part = false; |         if (item) | ||||||
|         wxString og_name = wxEmptyString; |         { | ||||||
|         if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { |             const bool is_settings_item = m_objects_model->IsSettingsItem(item); | ||||||
|             obj_idx = m_objects_model->GetIdByItem(item); |             bool is_part = false; | ||||||
|             og_name = _(L("Object manipulation")); |             wxString og_name = wxEmptyString; | ||||||
|             m_config = &(*m_objects)[obj_idx]->config; |             if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { | ||||||
|         } |                 obj_idx = m_objects_model->GetIdByItem(item); | ||||||
|         else { |                 og_name = _(L("Object manipulation")); | ||||||
|             auto parent = m_objects_model->GetParent(item); |                 m_config = &(*m_objects)[obj_idx]->config; | ||||||
|             // 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); |             else { | ||||||
|             if (is_settings_item) { |                 auto parent = m_objects_model->GetParent(item); | ||||||
|                 if (m_objects_model->GetParent(parent) == wxDataViewItem(0)) { |                 // Take ID of the parent object to "inform" perl-side which object have to be selected on the scene
 | ||||||
|                     og_name = _(L("Object Settings to modify")); |                 obj_idx = m_objects_model->GetIdByItem(parent); | ||||||
|                     m_config = &(*m_objects)[obj_idx]->config; |                 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 { |                 else if (m_objects_model->GetItemType(item) == itVolume) { | ||||||
|                     og_name = _(L("Part Settings to modify")); |                     og_name = _(L("Part manipulation")); | ||||||
|                     is_part = true; |                     is_part = true; | ||||||
|                     auto main_parent = m_objects_model->GetParent(parent); |                     const auto volume_id = m_objects_model->GetVolumeIdByItem(item); | ||||||
|                     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; |                     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 + " "); |             og->set_name(" " + og_name + " "); | ||||||
|         object_name = m_objects_model->GetName(item); |             object_name = m_objects_model->GetName(item); | ||||||
|         if (m_default_config) delete m_default_config; |             if (m_default_config) delete m_default_config; | ||||||
|         m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(is_part)); |             m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(is_part)); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     og->set_value("object_name", object_name); |     og->set_value("object_name", object_name); | ||||||
| 
 | 
 | ||||||
|  | @ -1209,13 +1218,20 @@ void ObjectList::update_selections() | ||||||
|     auto& selection = _3DScene::get_canvas(wxGetApp().canvas3D())->get_selection(); |     auto& selection = _3DScene::get_canvas(wxGetApp().canvas3D())->get_selection(); | ||||||
|     wxDataViewItemArray sels; |     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()) { |         for (auto idx : selection.get_volume_idxs()) { | ||||||
|             const auto gl_vol = selection.get_volume(idx); |             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()) {             |         for (auto idx : selection.get_instance_idxs()) {             | ||||||
|             sels.Add(m_objects_model->GetItemByInstanceId(selection.get_object_idx(), idx)); |             sels.Add(m_objects_model->GetItemByInstanceId(selection.get_object_idx(), idx)); | ||||||
|         } |         } | ||||||
|  | @ -1303,6 +1319,27 @@ void ObjectList::select_all() | ||||||
|     selection_changed(); |     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() | void ObjectList::fix_multiselection_conflicts() | ||||||
| { | { | ||||||
|     if (GetSelectedItemsCount() <= 1) |     if (GetSelectedItemsCount() <= 1) | ||||||
|  | @ -1314,7 +1351,7 @@ void ObjectList::fix_multiselection_conflicts() | ||||||
|     GetSelections(sels); |     GetSelections(sels); | ||||||
| 
 | 
 | ||||||
|     for (auto item : sels) { |     for (auto item : sels) { | ||||||
|         if (m_objects_model->IsSettingsItem(item)) |         if (m_objects_model->GetItemType(item) & (itSettings|itInstanceRoot)) | ||||||
|             Unselect(item); |             Unselect(item); | ||||||
|         else if (m_objects_model->GetParent(item) != wxDataViewItem(0)) |         else if (m_objects_model->GetParent(item) != wxDataViewItem(0)) | ||||||
|             Unselect(m_objects_model->GetParent(item)); |             Unselect(m_objects_model->GetParent(item)); | ||||||
|  |  | ||||||
|  | @ -143,6 +143,7 @@ public: | ||||||
|     void select_item(const wxDataViewItem& item); |     void select_item(const wxDataViewItem& item); | ||||||
|     void select_items(const wxDataViewItemArray& sels); |     void select_items(const wxDataViewItemArray& sels); | ||||||
|     void select_all(); |     void select_all(); | ||||||
|  |     void select_item_all_children(); | ||||||
|     // correct current selections to avoid of the possible conflicts
 |     // correct current selections to avoid of the possible conflicts
 | ||||||
|     void fix_multiselection_conflicts(); |     void fix_multiselection_conflicts(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1839,9 +1839,9 @@ bool Plater::priv::init_object_menu() | ||||||
|         return false; |         return false; | ||||||
| 
 | 
 | ||||||
|     wxMenuItem* item_split_objects = append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")), |     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")), |     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"); |     wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "shape_ungroup.png"); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
 tamasmeszaros
						tamasmeszaros