diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 8e37be13f..59b92df97 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -3085,6 +3085,17 @@ void ModelVolume::update_extruder_count(size_t extruder_count) } } +void ModelVolume::update_extruder_count_when_delete_filament(size_t extruder_count, size_t filament_id) +{ + std::vector used_extruders = get_extruders(); + for (int extruder_id : used_extruders) { + if (extruder_id == filament_id) { + mmu_segmentation_facets.set_enforcer_block_type_limit(*this, (EnforcerBlockerType)(extruder_count + 1), (EnforcerBlockerType) filament_id); + break; + } + } +} + void ModelVolume::center_geometry_after_creation(bool update_source_offset) { Vec3d shift = this->mesh().bounding_box().center(); @@ -3982,10 +3993,10 @@ void FacetsAnnotation::get_facets(const ModelVolume& mv, std::vectorset(selector); } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index d377276bd..689d71347 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -770,7 +770,7 @@ public: indexed_triangle_set get_facets(const ModelVolume& mv, EnforcerBlockerType type) const; // BBS void get_facets(const ModelVolume& mv, std::vector& facets_per_type) const; - void set_enforcer_block_type_limit(const ModelVolume& mv, EnforcerBlockerType max_type); + void set_enforcer_block_type_limit(const ModelVolume& mv, EnforcerBlockerType max_type, EnforcerBlockerType to_delete_filament = EnforcerBlockerType::NONE); indexed_triangle_set get_facets_strict(const ModelVolume& mv, EnforcerBlockerType type) const; bool has_facets(const ModelVolume& mv, EnforcerBlockerType type) const; bool empty() const { return m_data.first.empty(); } @@ -974,6 +974,7 @@ public: // BBS std::vector get_extruders() const; void update_extruder_count(size_t extruder_count); + void update_extruder_count_when_delete_filament(size_t extruder_count, size_t filament_id); // Split this volume, append the result to the object owning this volume. // Return the number of volumes created from this one. diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index 0250f714d..3157f8cbd 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -1745,6 +1745,30 @@ void PresetBundle::set_num_filaments(unsigned int n, std::string new_color) update_multi_material_filament_presets(); } +void PresetBundle::update_num_filaments(unsigned int to_del_flament_id) +{ + int old_filament_count = this->filament_presets.size(); + assert(to_del_flament_id < old_filament_count); + filament_presets.erase(filament_presets.begin() + to_del_flament_id); + + ConfigOptionStrings *filament_color = project_config.option("filament_colour"); + if (filament_color->values.size() > to_del_flament_id) { + filament_color->values.erase(filament_color->values.begin() + to_del_flament_id); + } + else { + filament_color->values.resize(to_del_flament_id); + } + + if (ams_multi_color_filment.size() > to_del_flament_id){ + ams_multi_color_filment.erase(ams_multi_color_filment.begin() + to_del_flament_id); + } + else { + ams_multi_color_filment.resize(to_del_flament_id); + } + + update_multi_material_filament_presets(to_del_flament_id); +} + unsigned int PresetBundle::sync_ams_list(unsigned int &unknowns) { std::vector filament_presets; @@ -3613,7 +3637,7 @@ std::pair PresetBundle::load_vendor_configs_ return std::make_pair(std::move(substitutions), presets_loaded); } -void PresetBundle::update_multi_material_filament_presets() +void PresetBundle::update_multi_material_filament_presets(size_t to_delete_filament_id) { if (printers.get_edited_preset().printer_technology() != ptFFF) return; @@ -3631,6 +3655,8 @@ void PresetBundle::update_multi_material_filament_presets() #else size_t num_filaments = this->filament_presets.size(); #endif + if (to_delete_filament_id == -1) + to_delete_filament_id = num_filaments; // Now verify if flush_volumes_matrix has proper size (it is used to deduce number of extruders in wipe tower generator): std::vector old_matrix = this->project_config.option("flush_volumes_matrix")->values; @@ -3649,38 +3675,24 @@ void PresetBundle::update_multi_material_filament_presets() filaments.pop_back(); } - if (nozzle_nums > 1) { - size_t old_matrix_size = old_number_of_filaments * old_number_of_filaments; - size_t new_matrix_size = num_filaments * num_filaments; - std::vector new_matrix(new_matrix_size * nozzle_nums, 0); - for (unsigned int i = 0; i < num_filaments; ++i) - for (unsigned int j = 0; j < num_filaments; ++j) { - if (i < old_number_of_filaments && j < old_number_of_filaments) { - for (size_t nozzle_id = 0; nozzle_id < nozzle_nums; ++nozzle_id) { - new_matrix[i * num_filaments + j + new_matrix_size * nozzle_id] = old_matrix[i * old_number_of_filaments + j + old_matrix_size * nozzle_id]; - } + size_t old_matrix_size = old_number_of_filaments * old_number_of_filaments; + size_t new_matrix_size = num_filaments * num_filaments; + std::vector new_matrix(new_matrix_size * nozzle_nums, 0); + for (unsigned int i = 0; i < num_filaments; ++i) + for (unsigned int j = 0; j < num_filaments; ++j) { + if (i < old_number_of_filaments && j < old_number_of_filaments) { + unsigned int old_i = i >= to_delete_filament_id ? i + 1 : i; + unsigned int old_j = j >= to_delete_filament_id ? j + 1 : j; + for (size_t nozzle_id = 0; nozzle_id < nozzle_nums; ++nozzle_id) { + new_matrix[i * num_filaments + j + new_matrix_size * nozzle_id] = old_matrix[old_i * old_number_of_filaments + old_j + old_matrix_size * nozzle_id]; } - else { - for (size_t nozzle_id = 0; nozzle_id < nozzle_nums; ++nozzle_id) { - new_matrix[i * num_filaments + j + new_matrix_size * nozzle_id] = (i == j ? 0. : filaments[2 * i] + filaments[2 * j + 1]); - } + } else { + for (size_t nozzle_id = 0; nozzle_id < nozzle_nums; ++nozzle_id) { + new_matrix[i * num_filaments + j + new_matrix_size * nozzle_id] = (i == j ? 0. : filaments[2 * i] + filaments[2 * j + 1]); } } - this->project_config.option("flush_volumes_matrix")->values = new_matrix; - } - else { - std::vector new_matrix; - for (unsigned int i = 0; i < num_filaments; ++i) - for (unsigned int j = 0; j < num_filaments; ++j) { - // append the value for this pair from the old matrix (if it's there): - if (i < old_number_of_filaments && j < old_number_of_filaments) - new_matrix.push_back(old_matrix[i * old_number_of_filaments + j]); - else - new_matrix.push_back(i == j ? 0. : filaments[2 * i] + filaments[2 * j + 1]); // so it matches new extruder volumes - } - this->project_config.option("flush_volumes_matrix")->values = new_matrix; - } - + } + this->project_config.option("flush_volumes_matrix")->values = new_matrix; } } diff --git a/src/libslic3r/PresetBundle.hpp b/src/libslic3r/PresetBundle.hpp index 0942e45ea..c435bed42 100644 --- a/src/libslic3r/PresetBundle.hpp +++ b/src/libslic3r/PresetBundle.hpp @@ -95,6 +95,7 @@ public: // BBS void set_num_filaments(unsigned int n, std::string new_col = ""); + void update_num_filaments(unsigned int to_del_flament_id); unsigned int sync_ams_list(unsigned int & unknowns); //BBS: check whether this is the only edited filament bool is_the_only_edited_filament(unsigned int filament_index); @@ -214,7 +215,7 @@ public: // Read out the number of extruders from an active printer preset, // update size and content of filament_presets. - void update_multi_material_filament_presets(); + void update_multi_material_filament_presets(size_t to_delete_filament_id = size_t(-1)); // Update the is_compatible flag of all print and filament presets depending on whether they are marked // as compatible with the currently selected printer (and print in case of filament presets). diff --git a/src/libslic3r/TriangleSelector.cpp b/src/libslic3r/TriangleSelector.cpp index 5f2b3fcb1..361efa983 100644 --- a/src/libslic3r/TriangleSelector.cpp +++ b/src/libslic3r/TriangleSelector.cpp @@ -1701,7 +1701,7 @@ std::pair>, std::vector> TriangleSelector: return out.data; } -void TriangleSelector::deserialize(const std::pair>, std::vector> &data, bool needs_reset, EnforcerBlockerType max_ebt) +void TriangleSelector::deserialize(const std::pair>, std::vector> &data, bool needs_reset, EnforcerBlockerType max_ebt, EnforcerBlockerType to_delete_filament) { if (needs_reset) reset(); // dump any current state @@ -1767,6 +1767,10 @@ void TriangleSelector::deserialize(const std::pair max_ebt) state = EnforcerBlockerType::NONE; + if (to_delete_filament != EnforcerBlockerType::NONE && state != EnforcerBlockerType::NONE) { + state = state > to_delete_filament ? EnforcerBlockerType((int)state - 1) : state; + } + // Only valid if is_split. int special_side = code >> 2; diff --git a/src/libslic3r/TriangleSelector.hpp b/src/libslic3r/TriangleSelector.hpp index 8167db220..01da9f857 100644 --- a/src/libslic3r/TriangleSelector.hpp +++ b/src/libslic3r/TriangleSelector.hpp @@ -276,7 +276,10 @@ public: std::pair>, std::vector> serialize() const; // Load serialized data. Assumes that correct mesh is loaded. - void deserialize(const std::pair>, std::vector>& data, bool needs_reset = true, EnforcerBlockerType max_ebt = EnforcerBlockerType::ExtruderMax); + void deserialize(const std::pair>, std::vector> &data, + bool needs_reset = true, + EnforcerBlockerType max_ebt = EnforcerBlockerType::ExtruderMax, + EnforcerBlockerType to_delete_filament = EnforcerBlockerType::NONE); // For all triangles, remove the flag indicating that the triangle was selected by seed fill. void seed_fill_unselect_all_triangles(); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index c589435ac..1364e6711 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -699,6 +699,58 @@ void ObjectList::update_filament_values_for_items(const size_t filaments_count) wxGetApp().plater()->update(); } +void ObjectList::update_filament_values_for_items_when_delete_filament(const size_t filament_id) +{ + for (size_t i = 0; i < m_objects->size(); ++i) { + wxDataViewItem item = m_objects_model->GetItemById(i); + if (!item) + continue; + + auto object = (*m_objects)[i]; + wxString extruder; + if (!object->config.has("extruder") || size_t(object->config.extruder()) == filament_id + 1) { + extruder = "1"; + object->config.set_key_value("extruder", new ConfigOptionInt(1)); + } else { + int new_extruder = object->config.extruder() > filament_id ? object->config.extruder() - 1 : object->config.extruder(); + extruder = wxString::Format("%d", new_extruder); + object->config.set_key_value("extruder", new ConfigOptionInt(new_extruder)); + } + m_objects_model->SetExtruder(extruder, item); + + static const char *keys[] = {"support_filament", "support_interface_filament"}; + for (auto key : keys) + if (object->config.has(key) && object->config.opt_int(key) == filament_id + 1) + object->config.erase(key); + + if (object->volumes.size() > 1) { + for (size_t id = 0; id < object->volumes.size(); id++) { + item = m_objects_model->GetItemByVolumeId(i, id); + if (!item) continue; + if (!object->volumes[id]->config.has("extruder") || size_t(object->volumes[id]->config.extruder()) == filament_id + 1) { + int new_extruder = object->config.extruder() > filament_id ? object->config.extruder() - 1 : object->config.extruder(); + extruder = wxString::Format("%d", new_extruder); + object->config.set_key_value("extruder", new ConfigOptionInt(new_extruder)); + } else { + int new_extruder = object->volumes[id]->config.extruder() > filament_id ? object->volumes[id]->config.extruder() - 1 : object->volumes[id]->config.extruder(); + extruder = wxString::Format("%d", new_extruder); + object->volumes[id]->config.set_key_value("extruder", new ConfigOptionInt(new_extruder)); + } + + m_objects_model->SetExtruder(extruder, item); + + for (auto key : keys) + if (object->volumes[id]->config.has(key) && object->volumes[id]->config.opt_int(key) == filament_id + 1) + object->volumes[id]->config.erase(key); + } + } + } + + // BBS + wxGetApp().plater()->update(); +} + + void ObjectList::update_plate_values_for_items() { #ifdef __WXOSX__ @@ -844,6 +896,24 @@ void ObjectList::update_objects_list_filament_column(size_t filaments_count) m_prevent_update_filament_in_config = false; } +void ObjectList::update_objects_list_filament_column_when_delete_filament(size_t filament_id, size_t filaments_count) +{ + m_prevent_update_filament_in_config = true; + + // BBS: update extruder values even when filaments_count is 1, because it may be reduced from value greater than 1 + if (m_objects) + update_filament_values_for_items_when_delete_filament(filament_id); + + update_filament_colors(); + + // set show/hide for this column + set_filament_column_hidden(filaments_count == 1); + // a workaround for a wrong last column width updating under OSX + GetColumn(colEditing)->SetWidth(25); + + m_prevent_update_filament_in_config = false; +} + void ObjectList::update_filament_colors() { m_objects_model->UpdateColumValues(colFilament); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 4462b9bd0..a9c151c24 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -222,6 +222,7 @@ public: void create_objects_ctrl(); // BBS void update_objects_list_filament_column(size_t filaments_count); + void update_objects_list_filament_column_when_delete_filament(size_t filament_id, size_t filaments_count); void update_filament_colors(); // show/hide "Extruder" column for Objects List void set_filament_column_hidden(const bool hide) const; @@ -238,6 +239,7 @@ public: void update_name_in_model(const wxDataViewItem& item) const; void update_name_in_list(int obj_idx, int vol_idx) const; void update_filament_values_for_items(const size_t filaments_count); + void update_filament_values_for_items_when_delete_filament(const size_t filament_id); //BBS: update plate void update_plate_values_for_items(); diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index a05a34326..862a188ca 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -2738,6 +2738,37 @@ void PartPlate::update_first_layer_print_sequence(size_t filament_nums) } } +void PartPlate::update_first_layer_print_sequence_when_delete_filament(size_t filament_id) +{ + auto other_layers_seqs = get_other_layers_print_sequence(); + if (!other_layers_seqs.empty()) { + bool need_update_data = false; + for (auto &other_layers_seq : other_layers_seqs) { + std::vector &orders = other_layers_seq.second; + orders.erase(std::remove_if(orders.begin(), orders.end(), [filament_id](int n) { return n == filament_id +1; }), orders.end()); + for (auto &order : orders) { + order = order > filament_id ? order - 1 : order; + } + need_update_data = true; + } + if (need_update_data) + set_other_layers_print_sequence(other_layers_seqs); + } + + ConfigOptionInts *op_print_sequence_1st = m_config.option("first_layer_print_sequence"); + if (!op_print_sequence_1st) + return; + + std::vector &print_sequence_1st = op_print_sequence_1st->values; + if (print_sequence_1st.size() == 0 || print_sequence_1st[0] == 0) + return; + + print_sequence_1st.erase(std::remove_if(print_sequence_1st.begin(), print_sequence_1st.end(), [filament_id](int n) { return n == filament_id + 1; }), print_sequence_1st.end()); + for (auto &order : print_sequence_1st) { + order = order > filament_id ? order - 1 : order; + } +} + void PartPlate::print() const { unsigned int count=0; diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 746e351bf..c5f7154e6 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -469,6 +469,7 @@ public: void set_first_layer_print_sequence(const std::vector &sorted_filaments); void set_other_layers_print_sequence(const std::vector& layer_seq_list); void update_first_layer_print_sequence(size_t filament_nums); + void update_first_layer_print_sequence_when_delete_filament(size_t filamen_id); void print() const; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index ee50a61e2..d1f177e88 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1839,6 +1839,61 @@ void Sidebar::on_filaments_change(size_t num_filaments) dynamic_filament_list.update(); } +void Sidebar::on_filaments_delete(size_t filament_id) +{ + auto &choices = combos_filament(); + + if (filament_id >= choices.size()) + return; + + if (choices.size() == 1) + choices[0]->GetDropDown().Invalidate(); + + wxWindowUpdateLocker noUpdates_scrolled_panel(this); + + // delete UI item + if (filament_id < p->combos_filament.size()) { + const int last = p->combos_filament.size() - 1; + auto sizer_filaments = this->p->sizer_filaments->GetItem(last % 2)->GetSizer(); + sizer_filaments->Remove(last / 2); + + PlaterPresetComboBox* to_delete_combox = p->combos_filament[filament_id]; + (*p->combos_filament[last]).Destroy(); + p->combos_filament.pop_back(); + + // BBS: filament double columns + auto sizer_filaments0 = this->p->sizer_filaments->GetItem((size_t) 0)->GetSizer(); + auto sizer_filaments1 = this->p->sizer_filaments->GetItem(1)->GetSizer(); + if (p->combos_filament.size() < 2) { + sizer_filaments1->Clear(); + } else { + size_t c0 = sizer_filaments0->GetChildren().GetCount(); + size_t c1 = sizer_filaments1->GetChildren().GetCount(); + if (c0 < c1) + sizer_filaments1->Remove(c1 - 1); + else if (c0 > c1) + sizer_filaments1->AddStretchSpacer(1); + } + } + + auto sizer = p->m_panel_filament_title->GetSizer(); + if (p->m_flushing_volume_btn != nullptr && sizer != nullptr) { + if (p->combos_filament.size() > 1) + sizer->Show(p->m_flushing_volume_btn); + else + sizer->Hide(p->m_flushing_volume_btn); + } + + for (PlaterPresetComboBox *filament_combo : p->combos_filament) { + filament_combo->update(); + } + + Layout(); + p->m_panel_filament_title->Refresh(); + update_ui_from_settings(); + dynamic_filament_list.update(); +} + void Sidebar::add_filament() { // BBS: limit filament choices to ExtruderMax if (p->combos_filament.size() >= size_t(EnforcerBlockerType::ExtruderMax)) return; @@ -1846,20 +1901,27 @@ void Sidebar::add_filament() { add_custom_filament(new_col); } -void Sidebar::delete_filament() { +void Sidebar::delete_filament(size_t filament_id) { if (p->combos_filament.size() <= 1) return; wxBusyCursor busy; size_t filament_count = p->combos_filament.size() - 1; - if (wxGetApp().preset_bundle->is_the_only_edited_filament(filament_count) || (filament_count == 1)) { + if (filament_id == size_t(-1)) { + filament_id = filament_count; + } + + if (filament_id > filament_count) + return; + + if (wxGetApp().preset_bundle->is_the_only_edited_filament(filament_id) || (filament_id == 1)) { wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0], false, "", true); } - if (p->editing_filament >= filament_count) { + if (p->editing_filament == filament_id || p->editing_filament >= filament_count) { p->editing_filament = -1; } - wxGetApp().preset_bundle->set_num_filaments(filament_count); - wxGetApp().plater()->on_filaments_change(filament_count); + wxGetApp().preset_bundle->update_num_filaments(filament_id); + wxGetApp().plater()->on_filaments_delete(filament_count, filament_id); wxGetApp().get_tab(Preset::TYPE_PRINT)->update(); wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); } @@ -13138,6 +13200,51 @@ void Plater::on_filaments_change(size_t num_filaments) } } +void Plater::on_filaments_delete(size_t num_filaments, size_t filament_id) +{ + // only update elements in plater + update_filament_colors_in_full_config(); + + // update fisrt print sequence and other layer sequence + Slic3r::GUI::PartPlateList &plate_list = get_partplate_list(); + for (int i = 0; i < plate_list.get_plate_count(); ++i) { + PartPlate *part_plate = plate_list.get_plate(i); + part_plate->update_first_layer_print_sequence_when_delete_filament(filament_id); + } + + // update mmu info + for (ModelObject *mo : wxGetApp().model().objects) { + for (ModelVolume *mv : mo->volumes) { + mv->update_extruder_count_when_delete_filament(num_filaments, filament_id); + } + } + + // update UI + sidebar().on_filaments_delete(filament_id); + + // update global support filament + static const char *keys[] = {"support_filament", "support_interface_filament"}; + for (auto key : keys) + if (p->config->has(key) && p->config->opt_int(key) == filament_id + 1) + (*(p->config)).erase(key); + + // update object/volume/support(object and volume) filament id + sidebar().obj_list()->update_objects_list_filament_column_when_delete_filament(filament_id, num_filaments); + + // update customize gcode + for (auto& item = p->model.plates_custom_gcodes.begin(); item != p->model.plates_custom_gcodes.end(); ++item) { + auto iter = std::remove_if(item->second.gcodes.begin(), item->second.gcodes.end(), [filament_id](const Item& gcode_item) { + return (gcode_item.type == CustomGCode::Type::ToolChange && gcode_item.extruder == filament_id + 1); + }); + item->second.gcodes.erase(iter, item->second.gcodes.end()); + + for (auto& item : item->second.gcodes) { + if (item.type == CustomGCode::Type::ToolChange && item.extruder > filament_id) + item.extruder--; + } + } +} + void Plater::on_bed_type_change(BedType bed_type, bool is_gcode_file) { sidebar().set_is_gcode_file(is_gcode_file); sidebar().on_bed_type_change(bed_type); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 814d14a14..e1c393229 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -137,8 +137,10 @@ public: void jump_to_option(const std::string& opt_key, Preset::Type type, const std::wstring& category); // BBS. Add on_filaments_change() method. void on_filaments_change(size_t num_filaments); + void on_filaments_delete(size_t filament_id); + void add_filament(); - void delete_filament(); + void delete_filament(size_t filament_id = size_t(-1)); void add_custom_filament(wxColour new_col); // BBS void on_bed_type_change(BedType bed_type); @@ -429,6 +431,7 @@ public: bool leave_gizmos_stack(); void on_filaments_change(size_t extruders_count); + void on_filaments_delete(size_t extruders_count, size_t filament_id); // BBS void on_bed_type_change(BedType bed_type,bool is_gcode_file = false); bool update_filament_colors_in_full_config();