diff --git a/resources/icons/add_negative.svg b/resources/icons/add_negative.svg index 5f0afdcc3..99e37b7d7 100644 --- a/resources/icons/add_negative.svg +++ b/resources/icons/add_negative.svg @@ -3,10 +3,6 @@ - - - diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index e68eb7b6d..ce4b8311d 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -674,10 +674,10 @@ ModelVolume* ModelObject::add_volume(TriangleMesh &&mesh, ModelVolumeType type / return v; } -ModelVolume* ModelObject::add_volume(const ModelVolume &other, ModelVolumeType type /*= ModelVolumeType::MODEL_PART*/) +ModelVolume* ModelObject::add_volume(const ModelVolume &other, ModelVolumeType type /*= ModelVolumeType::INVALID*/) { ModelVolume* v = new ModelVolume(this, other); - if (v->type() != type) + if (type != ModelVolumeType::INVALID && v->type() != type) v->set_type(type); add_v_to_volumes(&(this->volumes), v); // The volume should already be centered at this point of time when copying shared pointers of the triangle mesh and convex hull. diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 69229860b..d665c7fe3 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -273,7 +273,7 @@ public: ModelVolume* add_volume(const TriangleMesh &mesh); ModelVolume* add_volume(TriangleMesh &&mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART); - ModelVolume* add_volume(const ModelVolume &volume, ModelVolumeType type = ModelVolumeType::MODEL_PART); + ModelVolume* add_volume(const ModelVolume &volume, ModelVolumeType type = ModelVolumeType::INVALID); ModelVolume* add_volume(const ModelVolume &volume, TriangleMesh &&mesh); void delete_volume(size_t idx); void clear_volumes(); diff --git a/src/slic3r/GUI/ExtraRenderers.cpp b/src/slic3r/GUI/ExtraRenderers.cpp index 584896dd5..59188c037 100644 --- a/src/slic3r/GUI/ExtraRenderers.cpp +++ b/src/slic3r/GUI/ExtraRenderers.cpp @@ -290,16 +290,11 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR labelRect.GetTopLeft(), wxSize(labelRect.GetWidth(), -1), 0, nullptr , wxCB_READONLY); - int i=0; - for (wxBitmap* bmp : icons) { - if (i==0) { - c_editor->Append(_L("default"), *bmp); - ++i; - } + int def_id = get_default_extruder_idx ? get_default_extruder_idx() : 0; + c_editor->Append(_L("default"), def_id < 0 ? wxNullBitmap : *icons[def_id]); + for (size_t i = 0; i < icons.size(); i++) + c_editor->Append(wxString::Format("%d", i+1), *icons[i]); - c_editor->Append(wxString::Format("%d", i), *bmp); - ++i; - } c_editor->SetSelection(atoi(data.GetText().c_str())); // to avoid event propagation to other sidebar items diff --git a/src/slic3r/GUI/ExtraRenderers.hpp b/src/slic3r/GUI/ExtraRenderers.hpp index 6593963b7..ef8336d39 100644 --- a/src/slic3r/GUI/ExtraRenderers.hpp +++ b/src/slic3r/GUI/ExtraRenderers.hpp @@ -152,10 +152,12 @@ public: bool GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) override; void set_can_create_editor_ctrl_function(std::function can_create_fn) { can_create_editor_ctrl = can_create_fn; } + void set_default_extruder_idx(std::function default_extruder_idx_fn) { get_default_extruder_idx = default_extruder_idx_fn; } private: DataViewBitmapText m_value; - std::function can_create_editor_ctrl { nullptr }; + std::function can_create_editor_ctrl { nullptr }; + std::function get_default_extruder_idx{ nullptr }; }; diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 6dab61c77..ee0dcc064 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -665,6 +665,12 @@ void MenuFactory::append_menu_item_change_extruder(wxMenu* menu) if (sels.IsEmpty()) return; + if (sels.Count() == 1) { + const auto sel_vol = obj_list()->get_selected_model_volume(); + if (sel_vol && sel_vol->type() != ModelVolumeType::MODEL_PART && sel_vol->type() != ModelVolumeType::PARAMETER_MODIFIER) + return; + } + std::vector icons = get_extruder_color_icons(true); wxMenu* extruder_selection_menu = new wxMenu(); const wxString& name = sels.Count() == 1 ? names[0] : names[1]; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 0b1245494..26a2f305b 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -296,6 +296,9 @@ void ObjectList::create_objects_ctrl() bmp_choice_renderer->set_can_create_editor_ctrl_function([this]() { return m_objects_model->GetItemType(GetSelection()) & (itVolume | itLayer | itObject); }); + bmp_choice_renderer->set_default_extruder_idx([this]() { + return m_objects_model->GetDefaultExtruderIdx(GetSelection()); + }); AppendColumn(new wxDataViewColumn(_L("Extruder"), bmp_choice_renderer, colExtruder, 8*em, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE)); @@ -3471,7 +3474,7 @@ void ObjectList::change_part_type() } } - const wxString names[] = { _L("Part"), _L("Negative Volume"), _L("Modifier"), _L("Support Enforcer"), _L("Support Blocker") }; + const wxString names[] = { _L("Part"), _L("Negative Volume"), _L("Modifier"), _L("Support Blocker"), _L("Support Enforcer") }; auto new_type = ModelVolumeType(wxGetSingleChoiceIndex(_L("Type:"), _L("Select type of part"), wxArrayString(5, names), int(type))); if (new_type == type || new_type == ModelVolumeType::INVALID) @@ -3819,8 +3822,12 @@ void ObjectList::ItemValueChanged(wxDataViewEvent &event) { if (event.GetColumn() == colName) update_name_in_model(event.GetItem()); - else if (event.GetColumn() == colExtruder) - update_extruder_in_config(event.GetItem()); + else if (event.GetColumn() == colExtruder) { + wxDataViewItem item = event.GetItem(); + if (m_objects_model->GetItemType(item) == itObject) + m_objects_model->UpdateVolumesExtruderBitmap(item); + update_extruder_in_config(item); + } } #ifdef __WXMSW__ @@ -3861,8 +3868,10 @@ void ObjectList::set_extruder_for_selected_items(const int extruder) const wxDataViewItemArray sels; GetSelections(sels); - if (!sels.empty()) - take_snapshot(_(L("Change Extruders"))); + if (sels.empty()) + return; + + take_snapshot(_L("Change Extruders")); for (const wxDataViewItem& item : sels) { diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index 43e364084..cc24a2c23 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -17,16 +17,6 @@ namespace GUI { wxDEFINE_EVENT(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, wxCommandEvent); -static wxBitmap get_extruder_color_icon(size_t extruder_idx, bool thin_icon = false) -{ - // Create the bitmap with color bars. - std::vector bmps = get_extruder_color_icons(thin_icon); - if (bmps.empty()) - return wxNullBitmap; - - return *bmps[extruder_idx >= bmps.size() ? 0 : extruder_idx]; -} - BitmapCache* m_bitmap_cache = nullptr; // ***************************************************************************** @@ -49,6 +39,24 @@ static constexpr char LayerIcon[] = "edit_layers_some"; static constexpr char WarningIcon[] = "exclamation"; static constexpr char InfoIcon[] = "info"; +ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent, + const wxString& sub_obj_name, + Slic3r::ModelVolumeType type, + const wxBitmap& bmp, + const wxString& extruder, + const int idx/* = -1*/) : + m_parent(parent), + m_name(sub_obj_name), + m_type(itVolume), + m_volume_type(type), + m_idx(idx), + m_extruder(type == Slic3r::ModelVolumeType::MODEL_PART || type == Slic3r::ModelVolumeType::PARAMETER_MODIFIER ? extruder : "") +{ + m_bmp = bmp; + set_action_and_extruder_icons(); + init_container(); +} + ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const InfoItemType info_type) : m_parent(parent), m_type(itInfo), @@ -137,12 +145,11 @@ void ObjectDataViewModelNode::set_action_and_extruder_icons() void ObjectDataViewModelNode::set_extruder_icon() { - if (m_type & (itInstance | itInstanceRoot | itLayerRoot)) + if (m_type & (itInstance | itInstanceRoot | itLayerRoot) || + ((m_type & itVolume) && m_volume_type != Slic3r::ModelVolumeType::MODEL_PART && m_volume_type != Slic3r::ModelVolumeType::PARAMETER_MODIFIER)) return; // don't set colored bitmap for Instance - int extruder_idx = atoi(m_extruder.c_str()); - if (extruder_idx > 0) --extruder_idx; - m_extruder_bmp = get_extruder_color_icon(extruder_idx); + UpdateExtruderAndColorIcon(); } void ObjectDataViewModelNode::set_printable_icon(PrintIndicator printable) @@ -238,6 +245,39 @@ void ObjectDataViewModelNode::SetIdx(const int& idx) m_name = wxString::Format(_(L("Instance %d")), m_idx + 1); } +void ObjectDataViewModelNode::UpdateExtruderAndColorIcon(wxString extruder /*= ""*/) +{ + if (m_type == itVolume && m_volume_type != ModelVolumeType::MODEL_PART && m_volume_type != ModelVolumeType::PARAMETER_MODIFIER) + return; + if (extruder.empty()) + extruder = m_extruder; + else + m_extruder = extruder; // update extruder + + // update color icon + size_t extruder_idx = atoi(extruder.c_str()); + if (extruder_idx == 0) { + if (m_type & itObject); + else if (m_type & itVolume && m_volume_type == ModelVolumeType::MODEL_PART) { + extruder_idx = atoi(m_parent->GetExtruder().c_str()); + } + else { + m_extruder_bmp = wxNullBitmap; + return; + } + } + + if (extruder_idx > 0) --extruder_idx; + // Create the bitmap with color bars. + std::vector bmps = get_extruder_color_icons(false);// use wide icons + if (bmps.empty()) { + m_extruder_bmp = wxNullBitmap; + return; + } + + m_extruder_bmp = *bmps[extruder_idx >= bmps.size() ? 0 : extruder_idx]; +} + // ***************************************************************************** // ---------------------------------------------------------------------------- // ObjectDataViewModel @@ -317,8 +357,7 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent if (create_frst_child && root->m_volumes_cnt == 0) { const Slic3r::ModelVolumeType type = Slic3r::ModelVolumeType::MODEL_PART; - const auto node = new ObjectDataViewModelNode(root, root->m_name, GetVolumeIcon(type, obj_errors), extruder_str, 0); - node->m_volume_type = type; + const auto node = new ObjectDataViewModelNode(root, root->m_name, type, GetVolumeIcon(type, obj_errors), extruder_str, 0); insert_position < 0 ? root->Append(node) : root->Insert(node, insert_position); // notify control @@ -347,7 +386,7 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent } } - const auto node = new ObjectDataViewModelNode(root, name, GetVolumeIcon(volume_type, has_errors), extruder_str, new_volume_id); + const auto node = new ObjectDataViewModelNode(root, name, volume_type, GetVolumeIcon(volume_type, has_errors), extruder_str, new_volume_id); insert_position < 0 ? root->Append(node) : root->Insert(node, insert_position); // if part with errors is added, but object wasn't marked, then mark it @@ -359,8 +398,6 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent ItemAdded(parent_item, child); root->m_volumes_cnt++; - node->m_volume_type = volume_type; - return child; } @@ -1068,20 +1105,36 @@ bool ObjectDataViewModel::UpdateColumValues(unsigned col) void ObjectDataViewModel::UpdateExtruderBitmap(wxDataViewItem item) { - wxString extruder = GetExtruder(item); - if (extruder.IsEmpty()) + if (!item.IsOk()) return; + ObjectDataViewModelNode* node = static_cast(item.GetID()); + node->UpdateExtruderAndColorIcon(); +} - // set extruder bitmap - int extruder_idx = atoi(extruder.c_str()); - if (extruder_idx > 0) --extruder_idx; +void ObjectDataViewModel::UpdateVolumesExtruderBitmap(wxDataViewItem obj_item) +{ + if (!obj_item.IsOk() || GetItemType(obj_item) != itObject) + return; + ObjectDataViewModelNode* obj_node = static_cast(obj_item.GetID()); + for (auto child : obj_node->GetChildren()) + if (child->GetVolumeType() == ModelVolumeType::MODEL_PART) + child->UpdateExtruderAndColorIcon(); +} - const DataViewBitmapText extruder_val(extruder, get_extruder_color_icon(extruder_idx)); +int ObjectDataViewModel::GetDefaultExtruderIdx(wxDataViewItem item) +{ + ItemType type = GetItemType(item); + if (type == itObject) + return 0; - wxVariant value; - value << extruder_val; - - SetValue(value, item, colExtruder); + if (type == itVolume && GetVolumeType(item) == ModelVolumeType::MODEL_PART) { + wxDataViewItem obj_item = GetParent(item); + int extruder_id = GetExtruderNumber(obj_item); + if (extruder_id > 0) extruder_id--; + return extruder_id; + } + + return -1; } void ObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx) @@ -1249,18 +1302,12 @@ bool ObjectDataViewModel::SetValue(const wxVariant &variant, const int item_idx, void ObjectDataViewModel::SetExtruder(const wxString& extruder, wxDataViewItem item) { - DataViewBitmapText extruder_val; - extruder_val.SetText(extruder); - - // set extruder bitmap - int extruder_idx = atoi(extruder.c_str()); - if (extruder_idx > 0) --extruder_idx; - extruder_val.SetBitmap(get_extruder_color_icon(extruder_idx)); - - wxVariant value; - value << extruder_val; - - SetValue(value, item, colExtruder); + if (!item.IsOk()) + return; + ObjectDataViewModelNode* node = static_cast(item.GetID()); + node->UpdateExtruderAndColorIcon(extruder); + if (node->GetType() == itObject) + UpdateVolumesExtruderBitmap(item); } void ObjectDataViewModel::AddAllChildren(const wxDataViewItem& parent) @@ -1520,14 +1567,19 @@ void ObjectDataViewModel::UpdateSettingsDigest(const wxDataViewItem &item, ItemChanged(item); } -void ObjectDataViewModel::SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type) +void ObjectDataViewModel::SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType volume_type) { if (!item.IsOk() || GetItemType(item) != itVolume) return; ObjectDataViewModelNode *node = static_cast(item.GetID()); - node->SetVolumeType(type); - node->SetBitmap(m_volume_bmps[int(type)]); + node->SetVolumeType(volume_type); + node->SetBitmap(m_volume_bmps[int(volume_type)]); + if (volume_type != Slic3r::ModelVolumeType::MODEL_PART && volume_type != Slic3r::ModelVolumeType::PARAMETER_MODIFIER) + node->SetExtruder(""); // hide extruder + else if (node->GetExtruder().IsEmpty()) + node->SetExtruder("default"); // show extruder ans set it to default + node->UpdateExtruderAndColorIcon(); ItemChanged(item); } diff --git a/src/slic3r/GUI/ObjectDataViewModel.hpp b/src/slic3r/GUI/ObjectDataViewModel.hpp index 93e092fc2..11a9225ca 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.hpp +++ b/src/slic3r/GUI/ObjectDataViewModel.hpp @@ -94,19 +94,10 @@ public: ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const wxString& sub_obj_name, + Slic3r::ModelVolumeType type, const wxBitmap& bmp, const wxString& extruder, - const int idx = -1 ) : - m_parent (parent), - m_name (sub_obj_name), - m_type (itVolume), - m_idx (idx), - m_extruder (extruder) - { - m_bmp = bmp; - set_action_and_extruder_icons(); - init_container(); - } + const int idx = -1); ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const t_layer_height_range& layer_range, @@ -184,6 +175,7 @@ public: bool SetValue(const wxVariant &variant, unsigned int col); void SetVolumeType(ModelVolumeType type) { m_volume_type = type; } void SetBitmap(const wxBitmap &icon) { m_bmp = icon; } + void SetExtruder(const wxString &extruder) { m_extruder = extruder; } const wxBitmap& GetBitmap() const { return m_bmp; } const wxString& GetName() const { return m_name; } ItemType GetType() const { return m_type; } @@ -192,7 +184,9 @@ public: int GetIdx() const { return m_idx; } ModelVolumeType GetVolumeType() { return m_volume_type; } t_layer_height_range GetLayerRange() const { return m_layer_range; } + wxString GetExtruder() { return m_extruder; } PrintIndicator IsPrintable() const { return m_printable; } + void UpdateExtruderAndColorIcon(wxString extruder = ""); // use this function only for childrens void AssignAllVal(ObjectDataViewModelNode& from_node) @@ -384,6 +378,8 @@ public: bool UpdateColumValues(unsigned col); void UpdateExtruderBitmap(wxDataViewItem item); + void UpdateVolumesExtruderBitmap(wxDataViewItem object_item); + int GetDefaultExtruderIdx(wxDataViewItem item); private: wxDataViewItem AddRoot(const wxDataViewItem& parent_item, const ItemType root_type);