From 084ea583fbde43cb540b602fe2e0a932d0304409 Mon Sep 17 00:00:00 2001 From: "zhimin.zeng" Date: Tue, 13 Sep 2022 14:36:51 +0800 Subject: [PATCH] FIX: support to import color in standard 3mf Change-Id: I631e3f62c4d996924efafdfe9352d1585ad4d130 (cherry picked from commit ec08a5194b45a98973eb53ab0022a0799238134c) --- src/libslic3r/Format/bbs_3mf.cpp | 74 ++++++++++++++++++++++++++++++++ src/libslic3r/Model.cpp | 10 +++-- src/slic3r/GUI/Plater.cpp | 24 +++++------ 3 files changed, 93 insertions(+), 15 deletions(-) diff --git a/src/libslic3r/Format/bbs_3mf.cpp b/src/libslic3r/Format/bbs_3mf.cpp index 697a07730..6a29d8196 100644 --- a/src/libslic3r/Format/bbs_3mf.cpp +++ b/src/libslic3r/Format/bbs_3mf.cpp @@ -160,6 +160,8 @@ const unsigned int METADATA_STR_LEN = 9; static constexpr const char* MODEL_TAG = "model"; static constexpr const char* RESOURCES_TAG = "resources"; +static constexpr const char* COLOR_GROUP_TAG = "m:colorgroup"; +static constexpr const char* COLOR_TAG = "m:color"; static constexpr const char* OBJECT_TAG = "object"; static constexpr const char* MESH_TAG = "mesh"; static constexpr const char* MESH_STAT_TAG = "mesh_stat"; @@ -193,6 +195,7 @@ static constexpr const char* SLICE_HEADER_ITEM_TAG = "header_item"; // BBS: encrypt static constexpr const char* RELATIONSHIP_TAG = "Relationship"; +static constexpr const char* PID_ATTR = "pid"; static constexpr const char* PUUID_ATTR = "p:uuid"; static constexpr const char* PPATH_ATTR = "p:path"; static constexpr const char* OBJECT_UUID_SUFFIX = "-41cb-4c03-9d28-80fed5dfa1dc"; @@ -203,6 +206,7 @@ static constexpr const char* RELS_TYPE_ATTR = "Type"; static constexpr const char* UNIT_ATTR = "unit"; static constexpr const char* NAME_ATTR = "name"; +static constexpr const char* COLOR_ATTR = "color"; static constexpr const char* TYPE_ATTR = "type"; static constexpr const char* ID_ATTR = "id"; static constexpr const char* X_ATTR = "x"; @@ -549,6 +553,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) //int subobject_id; std::string name; std::string uuid; + int pid{-1}; //bool is_model_object; CurrentObject() { reset(); } @@ -713,6 +718,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) PlateData* m_curr_plater; CurrentInstance m_curr_instance; + int m_current_color_group{-1}; + std::map m_group_id_to_color; + public: _BBS_3MF_Importer(); ~_BBS_3MF_Importer(); @@ -778,6 +786,12 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) bool _handle_start_object(const char** attributes, unsigned int num_attributes); bool _handle_end_object(); + bool _handle_start_color_group(const char **attributes, unsigned int num_attributes); + bool _handle_end_color_group(); + + bool _handle_start_color(const char **attributes, unsigned int num_attributes); + bool _handle_end_color(); + bool _handle_start_mesh(const char** attributes, unsigned int num_attributes); bool _handle_end_mesh(); @@ -1314,6 +1328,20 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) } } + std::map color_group_id_to_extruder_id_map; + std::map color_to_extruder_id_map; + int extruder_id = 0; + for (auto group_iter = m_group_id_to_color.begin(); group_iter != m_group_id_to_color.end(); ++group_iter) { + auto color_iter = color_to_extruder_id_map.find(group_iter->second); + if (color_iter == color_to_extruder_id_map.end()) { + ++extruder_id; + color_to_extruder_id_map[group_iter->second] = extruder_id; + color_group_id_to_extruder_id_map[group_iter->first] = extruder_id; + } else { + color_group_id_to_extruder_id_map[group_iter->first] = color_iter->second; + } + } + for (const IdToModelObjectMap::value_type& object : m_objects) { if (object.second >= int(m_model->objects.size())) { add_error("invalid object, id: "+std::to_string(object.first.second)); @@ -1383,6 +1411,18 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) volumes.emplace_back(object_id.second); } + IdToCurrentObjectMap::const_iterator current_object = m_current_objects.find(object.first); + if (current_object != m_current_objects.end()) { + // get name + model_object->name = current_object->second.name; + + // get color + auto extruder_itor = color_group_id_to_extruder_id_map.find(current_object->second.pid); + if (extruder_itor != color_group_id_to_extruder_id_map.end()) { + model_object->config.set_key_value("extruder", new ConfigOptionInt(extruder_itor->second)); + } + } + // select as volumes volumes_ptr = &volumes; } @@ -2213,6 +2253,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) res = _handle_start_resources(attributes, num_attributes); else if (::strcmp(OBJECT_TAG, name) == 0) res = _handle_start_object(attributes, num_attributes); + else if (::strcmp(COLOR_GROUP_TAG, name) == 0) + res = _handle_start_color_group(attributes, num_attributes); + else if (::strcmp(COLOR_TAG, name) == 0) + res = _handle_start_color(attributes, num_attributes); else if (::strcmp(MESH_TAG, name) == 0) res = _handle_start_mesh(attributes, num_attributes); else if (::strcmp(VERTICES_TAG, name) == 0) @@ -2251,6 +2295,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) res = _handle_end_resources(); else if (::strcmp(OBJECT_TAG, name) == 0) res = _handle_end_object(); + else if (::strcmp(COLOR_GROUP_TAG, name) == 0) + res = _handle_end_color_group(); + else if (::strcmp(COLOR_TAG, name) == 0) + res = _handle_end_color(); else if (::strcmp(MESH_TAG, name) == 0) res = _handle_end_mesh(); else if (::strcmp(VERTICES_TAG, name) == 0) @@ -2434,6 +2482,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) m_curr_object->name = bbs_get_attribute_value_string(attributes, num_attributes, NAME_ATTR); m_curr_object->uuid = bbs_get_attribute_value_string(attributes, num_attributes, PUUID_ATTR); + m_curr_object->pid = bbs_get_attribute_value_int(attributes, num_attributes, PID_ATTR); } return true; @@ -2543,6 +2592,31 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) return true; } + bool _BBS_3MF_Importer::_handle_start_color_group(const char **attributes, unsigned int num_attributes) + { + m_current_color_group = bbs_get_attribute_value_int(attributes, num_attributes, ID_ATTR); + return true; + } + + bool _BBS_3MF_Importer::_handle_end_color_group() + { + // do nothing + return true; + } + + bool _BBS_3MF_Importer::_handle_start_color(const char **attributes, unsigned int num_attributes) + { + std::string color = bbs_get_attribute_value_string(attributes, num_attributes, COLOR_ATTR); + m_group_id_to_color[m_current_color_group] = color; + return true; + } + + bool _BBS_3MF_Importer::_handle_end_color() + { + // do nothing + return true; + } + bool _BBS_3MF_Importer::_handle_start_mesh(const char** attributes, unsigned int num_attributes) { // reset current geometry diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index ba5516ba4..3d74e7897 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -608,11 +608,15 @@ void Model::convert_multipart_object(unsigned int max_extruders) // Revert the centering operation. trafo_volume.set_offset(trafo_volume.get_offset() - o->origin_translation); int counter = 1; - auto copy_volume = [o, max_extruders, &counter, &extruder_counter](ModelVolume *new_v) { + auto copy_volume = [o, v, max_extruders, &counter, &extruder_counter](ModelVolume *new_v) { assert(new_v != nullptr); new_v->name = (counter > 1) ? o->name + "_" + std::to_string(counter++) : o->name; - //BBS: use default extruder id - //new_v->config.set("extruder", auto_extruder_id(max_extruders, extruder_counter)); + //BBS: Use extruder priority: volumn > object > default + if (v->config.option("extruder")) + new_v->config.set("extruder", v->config.extruder()); + else if (o->config.option("extruder")) + new_v->config.set("extruder", o->config.extruder()); + return new_v; }; if (o->instances.empty()) { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2c93e416e..9059c0537 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2709,8 +2709,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ project_presets.size() % (en_3mf_file_type == En3mfType::From_BBS) % file_version.to_string(); // 1. add extruder for prusa model if the number of existing extruders is not enough - // 2. add extruder for BBS model if only import geometry - if (en_3mf_file_type == En3mfType::From_Prusa || (en_3mf_file_type == En3mfType::From_BBS && load_model && !load_config)) { + // 2. add extruder for BBS or Other model if only import geometry + if (en_3mf_file_type == En3mfType::From_Prusa || (load_model && !load_config)) { std::set extruderIds; for (ModelObject *o : model.objects) { if (o->config.option("extruder")) extruderIds.insert(o->config.extruder()); @@ -3082,16 +3082,16 @@ std::vector Plater::priv::load_files(const std::vector& input_ // convert_model_if(model, answer_convert_from_imperial_units == wxID_YES); } - // if (model.looks_like_multipart_object()) { - // MessageDialog msg_dlg(q, _L( - // "This file contains several objects positioned at multiple heights.\n" - // "Instead of considering them as multiple objects, should \n" - // "the file be loaded as a single object having multiple parts?") + "\n", - // _L("Multi-part object detected"), wxICON_WARNING | wxYES | wxNO); - // if (msg_dlg.ShowModal() == wxID_YES) { - // model.convert_multipart_object(filaments_cnt); - // } - //} + if (model.looks_like_multipart_object()) { + MessageDialog msg_dlg(q, _L( + "This file contains several objects positioned at multiple heights.\n" + "Instead of considering them as multiple objects, should \n" + "the file be loaded as a single object having multiple parts?") + "\n", + _L("Multi-part object detected"), wxICON_WARNING | wxYES | wxNO); + if (msg_dlg.ShowModal() == wxID_YES) { + model.convert_multipart_object(filaments_cnt); + } + } } // else if ((wxGetApp().get_mode() == comSimple) && (type_3mf || type_any_amf) && model_has_advanced_features(model)) { // MessageDialog msg_dlg(q, _L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?")+"\n",