From c431cbf2022c13019fb33f1f71ccf66a6ddc3e9a Mon Sep 17 00:00:00 2001 From: "lane.wei" Date: Mon, 14 Nov 2022 21:59:49 +0800 Subject: [PATCH] ENH: CLI: some refines of slicing 1. add support_used flag in sliced_info 2. use the old thumbnail if no need Change-Id: I8ad166978fe6f76f86b1ef014945dd70b26a6285 --- src/BambuStudio.cpp | 448 +++++++++++++++++-------------- src/libslic3r/Format/bbs_3mf.cpp | 36 ++- src/libslic3r/Format/bbs_3mf.hpp | 1 + src/libslic3r/Print.hpp | 3 + src/libslic3r/PrintApply.cpp | 10 +- src/slic3r/GUI/PartPlate.cpp | 66 +++-- 6 files changed, 329 insertions(+), 235 deletions(-) diff --git a/src/BambuStudio.cpp b/src/BambuStudio.cpp index cf5993377..4295026ef 100644 --- a/src/BambuStudio.cpp +++ b/src/BambuStudio.cpp @@ -654,9 +654,9 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << "start_gui="<< start_gui << std::endl; //BBS: add plate data related logic - PlateDataPtrs plate_data; + PlateDataPtrs plate_data_src; int arrange_option; - bool first_file = true, is_bbl_3mf = false, need_arrange = true; + bool first_file = true, is_bbl_3mf = false, need_arrange = true, has_thumbnails = false; Semver file_version; std::map orients_requirement; std::vector project_presets; @@ -696,7 +696,7 @@ int CLI::run(int argc, char **argv) // BBS: adjust whebackup //LoadStrategy strategy = LoadStrategy::LoadModel | LoadStrategy::LoadConfig|LoadStrategy::AddDefaultInstances; //if (load_aux) strategy = strategy | LoadStrategy::LoadAuxiliary; - model = Model::read_from_file(file, &config, &config_substitutions, strategy, &plate_data, &project_presets, &is_bbl_3mf, &file_version); + model = Model::read_from_file(file, &config, &config_substitutions, strategy, &plate_data_src, &project_presets, &is_bbl_3mf, &file_version); if (is_bbl_3mf) { if (!first_file) @@ -704,7 +704,7 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << "The BBL 3mf file should be placed at the first position, filename=" << file << "\n"; flush_and_exit(CLI_FILELIST_INVALID_ORDER); } - BOOST_LOG_TRIVIAL(info) << "the first file is a 3mf, got plate count:" << plate_data.size() << "\n"; + BOOST_LOG_TRIVIAL(info) << "the first file is a 3mf, got plate count:" << plate_data_src.size() << "\n"; need_arrange = false; for (ModelObject* o : model.objects) { @@ -841,10 +841,9 @@ int CLI::run(int argc, char **argv) plate_stride = partplate_list.plate_stride_x(); BOOST_LOG_TRIVIAL(info) << "bed size, x="< 0) + if (plate_data_src.size() > 0) { - partplate_list.load_from_3mf_structure(plate_data); - release_PlateData_list(plate_data); + partplate_list.load_from_3mf_structure(plate_data_src); } /*for (ModelObject *model_object : m_models[0].objects) for (ModelInstance *model_instance : model_object->instances) @@ -1088,6 +1087,7 @@ int CLI::run(int argc, char **argv) } BOOST_LOG_TRIVIAL(info) << "finished model pre-process commands\n"; + bool oriented_or_arranged = false; //BBS: add orient and arrange logic here for (auto& model : m_models) { @@ -1097,6 +1097,7 @@ int CLI::run(int argc, char **argv) { BOOST_LOG_TRIVIAL(info) << "Before process command, Orient object, name=" << o->name <<",id="<id().id<(m_print_config.option("filament_type")); const ConfigOptionStrings* filament_color = dynamic_cast(m_print_config.option("filament_colour")); @@ -1544,223 +1547,262 @@ int CLI::run(int argc, char **argv) it->color = filament_color?filament_color->get_at(it->id):"#FFFFFF"; //it->filament_id = filament_id?filament_id->get_at(it->id):"unknown"; } + + if (!plate_data->plate_thumbnail.is_valid()) { + if (!oriented_or_arranged && plate_data_src.size() > i) + plate_data->thumbnail_file = plate_data_src[i]->thumbnail_file; + BOOST_LOG_TRIVIAL(info) << boost::format("thumbnails stage: plate %1%'s thumbnail data is invalid, check the file %2% exist or not")%(i+1) %plate_data->thumbnail_file; + if (plate_data->thumbnail_file.empty() || (!boost::filesystem::exists(plate_data->thumbnail_file))) { + BOOST_LOG_TRIVIAL(info) << boost::format("thumbnails stage: plate %1%'s thumbnail file also not there, need to regenerate")%(i+1); + need_regenerate_thumbnail = true; + } + else { + BOOST_LOG_TRIVIAL(info) << boost::format("thumbnails stage: plate %1%'s thumbnail file exists, no need to regenerate")%(i+1); + } + } } - std::vector colors; - if (filament_color) { - colors= filament_color->vserialize(); - } - else - colors.push_back("#FFFFFF"); + if (need_regenerate_thumbnail) { + std::vector colors; + if (filament_color) { + colors= filament_color->vserialize(); + } + else + colors.push_back("#FFFFFF"); - std::vector> colors_out(colors.size()); - unsigned char rgb_color[3] = {}; - for (const std::string& color : colors) { - Slic3r::GUI::BitmapCache::parse_color(color, rgb_color); - size_t color_idx = &color - &colors.front(); - colors_out[color_idx] = { float(rgb_color[0]) / 255.f, float(rgb_color[1]) / 255.f, float(rgb_color[2]) / 255.f, 1.f }; - } + std::vector> colors_out(colors.size()); + unsigned char rgb_color[3] = {}; + for (const std::string& color : colors) { + Slic3r::GUI::BitmapCache::parse_color(color, rgb_color); + size_t color_idx = &color - &colors.front(); + colors_out[color_idx] = { float(rgb_color[0]) / 255.f, float(rgb_color[1]) / 255.f, float(rgb_color[2]) / 255.f, 1.f }; + } - int gl_major, gl_minor, gl_verbos; - glfwGetVersion(&gl_major, &gl_minor, &gl_verbos); - BOOST_LOG_TRIVIAL(info) << boost::format("opengl version %1%.%2%.%3%")%gl_major %gl_minor %gl_verbos; + int gl_major, gl_minor, gl_verbos; + glfwGetVersion(&gl_major, &gl_minor, &gl_verbos); + BOOST_LOG_TRIVIAL(info) << boost::format("opengl version %1%.%2%.%3%")%gl_major %gl_minor %gl_verbos; - glfwSetErrorCallback(glfw_callback); - int ret = glfwInit(); - if (ret == GLFW_FALSE) { - int code = glfwGetError(NULL); - BOOST_LOG_TRIVIAL(error) << "glfwInit return error, code " <(option))->getInt(); - for (int volume_idx = 0; volume_idx < (int)model_object.volumes.size(); ++ volume_idx) { - const ModelVolume &model_volume = *model_object.volumes[volume_idx]; - option = model_volume.config.option("extruder"); - if (option) extruder_id = (dynamic_cast(option))->getInt(); - //if (!model_volume.is_model_part()) - // continue; - for (int instance_idx = 0; instance_idx < (int)model_object.instances.size(); ++ instance_idx) { - const ModelInstance &model_instance = *model_object.instances[instance_idx]; - glvolume_collection.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, "volume", true); - //glvolume_collection.volumes.back()->geometry_id = key.geometry_id; - std::string color = filament_color?filament_color->get_at(extruder_id - 1):"#00FF00"; - - unsigned char rgb_color[3] = {}; - Slic3r::GUI::BitmapCache::parse_color(color, rgb_color); - glvolume_collection.volumes.back()->set_render_color( float(rgb_color[0]) / 255.f, float(rgb_color[1]) / 255.f, float(rgb_color[2]) / 255.f, 1.f); - - std::array new_color; - new_color[0] = float(rgb_color[0]) / 255.f; - new_color[1] = float(rgb_color[1]) / 255.f; - new_color[2] = float(rgb_color[2]) / 255.f; - new_color[3] = 1.f; - glvolume_collection.volumes.back()->set_color(new_color); - } + GLFWwindow* window = glfwCreateWindow(640, 480, "base_window", NULL, NULL); + if (window == NULL) + { + BOOST_LOG_TRIVIAL(error) << "Failed to create GLFW window" << std::endl; } + else + glfwMakeContextCurrent(window); } - - ThumbnailsParams thumbnail_params; - GLShaderProgram* shader = opengl_mgr.get_shader("gouraud_light"); - if (!shader) { - BOOST_LOG_TRIVIAL(error) << boost::format("can not get shader for rendering thumbnail"); + bool opengl_valid = opengl_mgr.init_gl(); + if (!opengl_valid) { + BOOST_LOG_TRIVIAL(error) << "init opengl failed! skip thumbnail generating" << std::endl; } else { - for (int i = 0; i < partplate_list.get_plate_count(); i++) { - Slic3r::GUI::PartPlate *part_plate = partplate_list.get_plate(i); - ThumbnailData * thumbnail_data = new ThumbnailData(); - unsigned int thumbnail_width = 256, thumbnail_height = 256; - const ThumbnailsParams thumbnail_params = {{}, false, true, true, true, i}; + BOOST_LOG_TRIVIAL(info) << "glewInit Sucess." << std::endl; + GLVolumeCollection glvolume_collection; + Model &model = m_models[0]; + int extruder_id = 1; + for (unsigned int obj_idx = 0; obj_idx < (unsigned int)model.objects.size(); ++ obj_idx) { + const ModelObject &model_object = *model.objects[obj_idx]; + const ConfigOption* option = model_object.config.option("extruder"); + if (option) + extruder_id = (dynamic_cast(option))->getInt(); + for (int volume_idx = 0; volume_idx < (int)model_object.volumes.size(); ++ volume_idx) { + const ModelVolume &model_volume = *model_object.volumes[volume_idx]; + option = model_volume.config.option("extruder"); + if (option) extruder_id = (dynamic_cast(option))->getInt(); + //if (!model_volume.is_model_part()) + // continue; + for (int instance_idx = 0; instance_idx < (int)model_object.instances.size(); ++ instance_idx) { + const ModelInstance &model_instance = *model_object.instances[instance_idx]; + glvolume_collection.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, "volume", true); + //glvolume_collection.volumes.back()->geometry_id = key.geometry_id; + std::string color = filament_color?filament_color->get_at(extruder_id - 1):"#00FF00"; - switch (Slic3r::GUI::OpenGLManager::get_framebuffers_type()) - { - case Slic3r::GUI::OpenGLManager::EFramebufferType::Arb: - { - BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: ARB"); - Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer(*thumbnail_data, - thumbnail_width, thumbnail_height, thumbnail_params, - partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho); - break; - } - case Slic3r::GUI::OpenGLManager::EFramebufferType::Ext: - { - BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: EXT"); - Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer_ext(*thumbnail_data, - thumbnail_width, thumbnail_height, thumbnail_params, - partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho); - break; - } - default: - BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: unknown"); - break; - } - thumbnails.push_back(thumbnail_data); + unsigned char rgb_color[3] = {}; + Slic3r::GUI::BitmapCache::parse_color(color, rgb_color); + glvolume_collection.volumes.back()->set_render_color( float(rgb_color[0]) / 255.f, float(rgb_color[1]) / 255.f, float(rgb_color[2]) / 255.f, 1.f); - //render calibration thumbnail - if (!part_plate->get_slice_result() || !part_plate->is_slice_result_valid()) { - BOOST_LOG_TRIVIAL(info) << boost::format("plate %1% doesn't have a valid sliced result, skip it")%(i+1); - calibration_thumbnails.push_back(new ThumbnailData()); - plate_bboxes.push_back(new PlateBBoxData()); - continue; - } - PrintBase *print_base=NULL; - Slic3r::GUI::GCodeResult *gcode_result = NULL; - int print_index; - part_plate->get_print(&print_base, &gcode_result, &print_index); - - Print *print = dynamic_cast(print_base); - - //don't render calibration picture - /*BuildVolume build_volume(part_plate->get_shape(), print_height); - const std::vector& exclude_bounding_box = part_plate->get_exclude_areas(); - Slic3r::GUI::GCodeViewer gcode_viewer; - gcode_viewer.init(ConfigOptionMode::comAdvanced, nullptr); - gcode_viewer.load(*gcode_result, *print, build_volume, exclude_bounding_box, false, ConfigOptionMode::comAdvanced, false); - - std::vector colors; - if (filament_color) - colors = filament_color->values; - gcode_viewer.refresh(*gcode_result, colors); - - ThumbnailData* calibration_data = new ThumbnailData(); - const ThumbnailsParams calibration_params = { {}, false, true, true, true, i }; - //BBS fixed size - const int cali_thumbnail_width = 2560; - const int cali_thumbnail_height = 2560; - gcode_viewer.render_calibration_thumbnail(*calibration_data, cali_thumbnail_width, cali_thumbnail_height, - calibration_params, partplate_list, opengl_mgr); - //generate_calibration_thumbnail(*calibration_data, thumbnail_width, thumbnail_height, calibration_params); - //*plate_bboxes[index] = p->generate_first_layer_bbox(); - calibration_thumbnails.push_back(calibration_data);*/ - - PlateBBoxData* plate_bbox = new PlateBBoxData(); - std::vector& id_bboxes = plate_bbox->bbox_objs; - BoundingBoxf bbox_all; - auto seq_print = m_print_config.option>("print_sequence"); - if ( seq_print && (seq_print->value == PrintSequence::ByObject)) - plate_bbox->is_seq_print = true; - - auto objects = print->objects(); - auto orig = part_plate->get_origin(); - Vec2d orig2d = { orig[0], orig[1] }; - - for (auto obj : objects) - { - BBoxData data; - auto bb_scaled = obj->get_first_layer_bbox(data.area, data.layer_height, data.name); - auto bb = unscaled(bb_scaled); - bb.min -= orig2d; - bb.max -= orig2d; - bbox_all.merge(bb); - data.area *= (SCALING_FACTOR * SCALING_FACTOR); // unscale area - data.id = obj->id().id; - data.bbox = { bb.min.x(),bb.min.y(),bb.max.x(),bb.max.y() }; - id_bboxes.emplace_back(std::move(data)); - } - // add wipe tower bounding box - if (print->has_wipe_tower()) { - BBoxData data; - auto wt_corners = print->first_layer_wipe_tower_corners(); - // when loading gcode.3mf, wipe tower info may not be correct - if (!wt_corners.empty()) { - BoundingBox bb_scaled = {wt_corners[0], wt_corners[2]}; - auto bb = unscaled(bb_scaled); - bb.min -= orig2d; - bb.max -= orig2d; - bbox_all.merge(bb); - data.name = "wipe_tower"; - data.id = partplate_list.get_curr_plate()->get_index() + 1000; - data.bbox = {bb.min.x(), bb.min.y(), bb.max.x(), bb.max.y()}; - id_bboxes.emplace_back(std::move(data)); + std::array new_color; + new_color[0] = float(rgb_color[0]) / 255.f; + new_color[1] = float(rgb_color[1]) / 255.f; + new_color[2] = float(rgb_color[2]) / 255.f; + new_color[3] = 1.f; + glvolume_collection.volumes.back()->set_color(new_color); } } - plate_bbox->bbox_all = { bbox_all.min.x(),bbox_all.min.y(),bbox_all.max.x(),bbox_all.max.y() }; - plate_bboxes.push_back(plate_bbox); + } + + ThumbnailsParams thumbnail_params; + GLShaderProgram* shader = opengl_mgr.get_shader("gouraud_light"); + if (!shader) { + BOOST_LOG_TRIVIAL(error) << boost::format("can not get shader for rendering thumbnail"); + } + else { + for (int i = 0; i < partplate_list.get_plate_count(); i++) { + Slic3r::GUI::PartPlate *part_plate = partplate_list.get_plate(i); + PlateData *plate_data = plate_data_list[i]; + if (plate_data->plate_thumbnail.is_valid()) { + thumbnails.push_back(&plate_data->plate_thumbnail); + BOOST_LOG_TRIVIAL(info) << boost::format("plate %1% has a valid thumbnail, width %2%, height %3%, directly using it")%(i+1) %plate_data->plate_thumbnail.width %plate_data->plate_thumbnail.height; + continue; + } + BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s thumbnail, need to regenerate")%(i+1); + ThumbnailData * thumbnail_data = new ThumbnailData(); + unsigned int thumbnail_width = 256, thumbnail_height = 256; + const ThumbnailsParams thumbnail_params = {{}, false, true, true, true, i}; + + switch (Slic3r::GUI::OpenGLManager::get_framebuffers_type()) + { + case Slic3r::GUI::OpenGLManager::EFramebufferType::Arb: + { + BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: ARB"); + Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer(*thumbnail_data, + thumbnail_width, thumbnail_height, thumbnail_params, + partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho); + break; + } + case Slic3r::GUI::OpenGLManager::EFramebufferType::Ext: + { + BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: EXT"); + Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer_ext(*thumbnail_data, + thumbnail_width, thumbnail_height, thumbnail_params, + partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho); + break; + } + default: + BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: unknown"); + break; + } + thumbnails.push_back(thumbnail_data); + BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s thumbnail,finished rendering")%(i+1); + } + } + } + //BBS: release glfw + glfwTerminate(); + } + else { + for (int i = 0; i < partplate_list.get_plate_count(); i++) { + PlateData *plate_data = plate_data_list[i]; + if (plate_data->plate_thumbnail.is_valid()) { + thumbnails.push_back(&plate_data->plate_thumbnail); + BOOST_LOG_TRIVIAL(info) << boost::format("plate %1% has a valid thumbnail data, width %2%, height %3%, directly using it")%(i+1) %plate_data->plate_thumbnail.width %plate_data->plate_thumbnail.height; } } } + //generate first layer bboxes + for (int i = 0; i < partplate_list.get_plate_count(); i++) { + Slic3r::GUI::PartPlate *part_plate = partplate_list.get_plate(i); + //render calibration thumbnail + if (!part_plate->get_slice_result() || !part_plate->is_slice_result_valid()) { + BOOST_LOG_TRIVIAL(info) << boost::format("plate %1% doesn't have a valid sliced result, skip it")%(i+1); + //calibration_thumbnails.push_back(new ThumbnailData()); + plate_bboxes.push_back(new PlateBBoxData()); + continue; + } + PrintBase *print_base=NULL; + Slic3r::GUI::GCodeResult *gcode_result = NULL; + int print_index; + part_plate->get_print(&print_base, &gcode_result, &print_index); + + Print *print = dynamic_cast(print_base); + + //don't render calibration picture + /*BuildVolume build_volume(part_plate->get_shape(), print_height); + const std::vector& exclude_bounding_box = part_plate->get_exclude_areas(); + Slic3r::GUI::GCodeViewer gcode_viewer; + gcode_viewer.init(ConfigOptionMode::comAdvanced, nullptr); + gcode_viewer.load(*gcode_result, *print, build_volume, exclude_bounding_box, false, ConfigOptionMode::comAdvanced, false); + + std::vector colors; + if (filament_color) + colors = filament_color->values; + gcode_viewer.refresh(*gcode_result, colors); + + ThumbnailData* calibration_data = new ThumbnailData(); + const ThumbnailsParams calibration_params = { {}, false, true, true, true, i }; + //BBS fixed size + const int cali_thumbnail_width = 2560; + const int cali_thumbnail_height = 2560; + gcode_viewer.render_calibration_thumbnail(*calibration_data, cali_thumbnail_width, cali_thumbnail_height, + calibration_params, partplate_list, opengl_mgr); + //generate_calibration_thumbnail(*calibration_data, thumbnail_width, thumbnail_height, calibration_params); + //*plate_bboxes[index] = p->generate_first_layer_bbox(); + calibration_thumbnails.push_back(calibration_data);*/ + + PlateBBoxData* plate_bbox = new PlateBBoxData(); + std::vector& id_bboxes = plate_bbox->bbox_objs; + BoundingBoxf bbox_all; + auto seq_print = m_print_config.option>("print_sequence"); + if ( seq_print && (seq_print->value == PrintSequence::ByObject)) + plate_bbox->is_seq_print = true; + + auto objects = print->objects(); + auto orig = part_plate->get_origin(); + Vec2d orig2d = { orig[0], orig[1] }; + + for (auto obj : objects) + { + BBoxData data; + auto bb_scaled = obj->get_first_layer_bbox(data.area, data.layer_height, data.name); + auto bb = unscaled(bb_scaled); + bb.min -= orig2d; + bb.max -= orig2d; + bbox_all.merge(bb); + data.area *= (SCALING_FACTOR * SCALING_FACTOR); // unscale area + data.id = obj->id().id; + data.bbox = { bb.min.x(),bb.min.y(),bb.max.x(),bb.max.y() }; + id_bboxes.emplace_back(std::move(data)); + } + // add wipe tower bounding box + if (print->has_wipe_tower()) { + BBoxData data; + auto wt_corners = print->first_layer_wipe_tower_corners(); + // when loading gcode.3mf, wipe tower info may not be correct + if (!wt_corners.empty()) { + BoundingBox bb_scaled = {wt_corners[0], wt_corners[2]}; + auto bb = unscaled(bb_scaled); + bb.min -= orig2d; + bb.max -= orig2d; + bbox_all.merge(bb); + data.name = "wipe_tower"; + data.id = partplate_list.get_curr_plate()->get_index() + 1000; + data.bbox = {bb.min.x(), bb.min.y(), bb.max.x(), bb.max.y()}; + id_bboxes.emplace_back(std::move(data)); + } + } + plate_bbox->bbox_all = { bbox_all.min.x(),bbox_all.min.y(),bbox_all.max.x(),bbox_all.max.y() }; + plate_bboxes.push_back(plate_bbox); + } + + #if defined(__linux__) || defined(__LINUX__) if (g_cli_callback_mgr.is_started()) { PrintBase::SlicingStatus slicing_status{95, "Exporting 3mf"}; @@ -1785,9 +1827,9 @@ int CLI::run(int argc, char **argv) delete plate_bboxes[i]; } - //BBS: release glfw - if (export_to_3mf) { - glfwTerminate(); + if (plate_data_src.size() > 0) + { + release_PlateData_list(plate_data_src); } #if defined(__linux__) || defined(__LINUX__) diff --git a/src/libslic3r/Format/bbs_3mf.cpp b/src/libslic3r/Format/bbs_3mf.cpp index c2f1c6404..23a797439 100644 --- a/src/libslic3r/Format/bbs_3mf.cpp +++ b/src/libslic3r/Format/bbs_3mf.cpp @@ -247,6 +247,8 @@ static constexpr const char* PLATE_IDX_ATTR = "index"; static constexpr const char* SLICE_PREDICTION_ATTR = "prediction"; static constexpr const char* SLICE_WEIGHT_ATTR = "weight"; static constexpr const char* OUTSIDE_ATTR = "outside"; +static constexpr const char* SUPPORT_USED_ATTR = "support_used"; + static constexpr const char* OBJECT_TYPE = "object"; static constexpr const char* VOLUME_TYPE = "volume"; @@ -1084,7 +1086,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) } //BBS progress point - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_STAGE_OPEN\n"); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_STAGE_OPEN, m_load_restore=%1%\n")%m_load_restore; if (proFn) { proFn(IMPORT_STAGE_OPEN, 0, 1, cb_cancel); if (cb_cancel) @@ -1500,7 +1502,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) // model.adjust_min_z(); //BBS progress point - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_STAGE_LOADING_PLATES, m_plater_data size %1%\n")%m_plater_data.size(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("import 3mf IMPORT_STAGE_LOADING_PLATES, m_plater_data size %1%, m_backup_path %2%\n")%m_plater_data.size() %m_backup_path; if (proFn) { proFn(IMPORT_STAGE_LOADING_PLATES, 0, 1, cb_cancel); if (cb_cancel) @@ -1530,12 +1532,14 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) plate_data_list[it->first-1]->gcode_prediction = it->second->gcode_prediction; plate_data_list[it->first-1]->gcode_weight = it->second->gcode_weight; plate_data_list[it->first-1]->toolpath_outside = it->second->toolpath_outside; + plate_data_list[it->first-1]->is_support_used = it->second->is_support_used; plate_data_list[it->first-1]->slice_filaments_info = it->second->slice_filaments_info; plate_data_list[it->first-1]->warnings = it->second->warnings; plate_data_list[it->first-1]->thumbnail_file = (m_load_restore || it->second->thumbnail_file.empty()) ? it->second->thumbnail_file : m_backup_path + "/" + it->second->thumbnail_file; plate_data_list[it->first-1]->pattern_file = (m_load_restore || it->second->pattern_file.empty()) ? it->second->pattern_file : m_backup_path + "/" + it->second->pattern_file; plate_data_list[it->first-1]->pattern_bbox_file = (m_load_restore || it->second->pattern_bbox_file.empty()) ? it->second->pattern_bbox_file : m_backup_path + "/" + it->second->pattern_bbox_file; plate_data_list[it->first-1]->config = it->second->config; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", plate %1%, thumbnail_file=%2%")%it->first %plate_data_list[it->first-1]->thumbnail_file; it++; } @@ -3206,6 +3210,11 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) if (m_curr_plater) std::istringstream(value) >> std::boolalpha >> m_curr_plater->toolpath_outside; } + else if (key == SUPPORT_USED_ATTR) + { + if (m_curr_plater) + std::istringstream(value) >> std::boolalpha >> m_curr_plater->is_support_used; + } } return true; @@ -4117,6 +4126,24 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) } } } + else if (!m_skip_static && plate_data_list.size() > 0) { + for (int i = 0; i < plate_data_list.size(); i++) { + PlateData *plate_data = plate_data_list[i]; + if (proFn) { + proFn(EXPORT_STAGE_ADD_THUMBNAILS, i, plate_data_list.size(), cb_cancel); + if (cb_cancel) + return false; + } + if (!plate_data->thumbnail_file.empty() && (boost::filesystem::exists(plate_data->thumbnail_file))){ + std::string dst_in_3mf = (boost::format("Metadata/plate_%1%.png") % (i + 1)).str(); + + if (!_add_file_to_archive(archive, dst_in_3mf, plate_data->thumbnail_file)) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", add thumbnail %1% from file %2% failed\n") % (i+1) %plate_data->thumbnail_file; + return false; + } + } + } + } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",before add calibration thumbnails, count %1%\n")%calibration_data.size(); //BBS add calibration thumbnail for each plate @@ -5604,6 +5631,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) std::string thumbnail_file_in_3mf = (boost::format(THUMBNAIL_FILE_FORMAT) % (plate_data->plate_index + 1)).str(); stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << THUMBNAIL_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << thumbnail_file_in_3mf << "\"/>\n"; } + else if (!plate_data->thumbnail_file.empty() && (boost::filesystem::exists(plate_data->thumbnail_file))){ + std::string thumbnail_file_in_3mf = (boost::format(THUMBNAIL_FILE_FORMAT) % (plate_data->plate_index + 1)).str(); + stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << THUMBNAIL_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << thumbnail_file_in_3mf << "\"/>\n"; + } if (!plate_data->pattern_file.empty()) { std::string pattern_file_in_3mf = (boost::format(PATTERN_FILE_FORMAT) % (plate_data->plate_index + 1)).str(); @@ -5713,6 +5744,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SLICE_PREDICTION_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->get_gcode_prediction_str() << "\"/>\n"; stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SLICE_WEIGHT_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->get_gcode_weight_str() << "\"/>\n"; stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << OUTSIDE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha<< plate_data->toolpath_outside << "\"/>\n"; + stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SUPPORT_USED_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha<< plate_data->is_support_used << "\"/>\n"; for (auto it = plate_data->slice_filaments_info.begin(); it != plate_data->slice_filaments_info.end(); it++) { diff --git a/src/libslic3r/Format/bbs_3mf.hpp b/src/libslic3r/Format/bbs_3mf.hpp index 43734bd39..4ba109bc4 100644 --- a/src/libslic3r/Format/bbs_3mf.hpp +++ b/src/libslic3r/Format/bbs_3mf.hpp @@ -68,6 +68,7 @@ struct PlateData std::string gcode_weight; std::vector slice_filaments_info; DynamicPrintConfig config; + bool is_support_used {false}; bool is_sliced_valid = false; bool toolpath_outside {false}; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 52f035308..3ebad48da 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -720,6 +720,8 @@ public: void export_gcode_from_previous_file(const std::string& file, GCodeProcessorResult* result, ThumbnailsGeneratorCallback thumbnail_cb = nullptr); //BBS: add modify_count logic int get_modified_count() const {return m_modified_count;} + //BBS: add status for whether support used + bool is_support_used() const {return m_support_used;} //BBS static StringObjectException sequential_print_clearance_valid(const Print &print, Polygons *polygons = nullptr, std::vector>* height_polygons = nullptr); @@ -769,6 +771,7 @@ private: // Estimated print time, filament consumed. PrintStatistics m_print_statistics; + bool m_support_used {false}; //BBS: plate's origin Vec3d m_origin; diff --git a/src/libslic3r/PrintApply.cpp b/src/libslic3r/PrintApply.cpp index 0c95d1d24..c36c79b9a 100644 --- a/src/libslic3r/PrintApply.cpp +++ b/src/libslic3r/PrintApply.cpp @@ -1031,6 +1031,11 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", i=%1%, key=%2%")%i %changed_keys[i]; } } + const ConfigOption* enable_support_option = new_full_config.option("enable_support"); + if (enable_support_option && enable_support_option->getBool()) + m_support_used = true; + else + m_support_used = false; // Find modified keys of the various configs. Resolve overrides extruder retract values by filament profiles. DynamicPrintConfig filament_overrides; @@ -1550,7 +1555,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ // If it is not valid, then it is ensured that PrintObject.m_slicing_params is not in use // (posSlicing and posSupportMaterial was invalidated). for (PrintObject *object : m_objects) + { object->update_slicing_parameters(); + m_support_used |= object->config().enable_support; + } #ifdef _DEBUG check_model_ids_equal(m_model, model); @@ -1559,7 +1567,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ //BBS: add timestamp logic if (apply_status != APPLY_STATUS_UNCHANGED) m_modified_count++; - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" %1%: finished, this %2%, m_modified_count %3%, apply_status %4%, ")%__LINE__ %this %m_modified_count %apply_status; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" %1%: finished, this %2%, m_modified_count %3%, apply_status %4%, m_support_used %5%")%__LINE__ %this %m_modified_count %apply_status %m_support_used; return static_cast(apply_status); } diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 485c9fafa..62613b281 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -4157,7 +4157,11 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w PlateData* plate_data_item = new PlateData(); plate_data_item->locked = m_plate_list[i]->m_locked; plate_data_item->plate_index = m_plate_list[i]->m_plate_index; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1% before load, width %2%, height %3%, size %4%!") + %(i+1) %m_plate_list[i]->thumbnail_data.width %m_plate_list[i]->thumbnail_data.height %m_plate_list[i]->thumbnail_data.pixels.size(); plate_data_item->plate_thumbnail.load_from(m_plate_list[i]->thumbnail_data); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1% after load, width %2%, height %3%, size %4%!") + %(i+1) %plate_data_item->plate_thumbnail.width %plate_data_item->plate_thumbnail.height %plate_data_item->plate_thumbnail.pixels.size(); plate_data_item->config.apply(*m_plate_list[i]->config()); if (m_plate_list[i]->obj_to_instance_set.size() > 0) @@ -4170,37 +4174,38 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w %i %m_plate_list[i]->m_gcode_result->filename % with_slice_info %m_plate_list[i]->is_slice_result_valid(); if (with_slice_info) { - if (m_plate_list[i]->get_slice_result() && m_plate_list[i]->is_slice_result_valid()) { - // BBS only include current palte_idx - if (plate_idx == i || plate_idx == PLATE_CURRENT_IDX || plate_idx == PLATE_ALL_IDX) { - //load calibration thumbnail - if (m_plate_list[i]->cali_thumbnail_data.is_valid()) - plate_data_item->pattern_file = "valid_pattern"; - if (m_plate_list[i]->cali_bboxes_data.is_valid()) - plate_data_item->pattern_bbox_file = "valid_pattern_bbox"; - plate_data_item->gcode_file = m_plate_list[i]->m_gcode_result->filename; - plate_data_item->is_sliced_valid = true; - plate_data_item->gcode_prediction = std::to_string( - (int) m_plate_list[i]->get_slice_result()->print_statistics.modes[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].time); - plate_data_item->toolpath_outside = m_plate_list[i]->m_gcode_result->toolpath_outside; - Print *print = nullptr; - m_plate_list[i]->get_print((PrintBase **) &print, nullptr, nullptr); - if (print) { - const PrintStatistics &ps = print->print_statistics(); - if (ps.total_weight != 0.0) { + if (m_plate_list[i]->get_slice_result() && m_plate_list[i]->is_slice_result_valid()) { + // BBS only include current palte_idx + if (plate_idx == i || plate_idx == PLATE_CURRENT_IDX || plate_idx == PLATE_ALL_IDX) { + //load calibration thumbnail + if (m_plate_list[i]->cali_thumbnail_data.is_valid()) + plate_data_item->pattern_file = "valid_pattern"; + if (m_plate_list[i]->cali_bboxes_data.is_valid()) + plate_data_item->pattern_bbox_file = "valid_pattern_bbox"; + plate_data_item->gcode_file = m_plate_list[i]->m_gcode_result->filename; + plate_data_item->is_sliced_valid = true; + plate_data_item->gcode_prediction = std::to_string( + (int) m_plate_list[i]->get_slice_result()->print_statistics.modes[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].time); + plate_data_item->toolpath_outside = m_plate_list[i]->m_gcode_result->toolpath_outside; + Print *print = nullptr; + m_plate_list[i]->get_print((PrintBase **) &print, nullptr, nullptr); + if (print) { + const PrintStatistics &ps = print->print_statistics(); + if (ps.total_weight != 0.0) { CNumericLocalesSetter locales_setter; plate_data_item->gcode_weight =wxString::Format("%.2f", ps.total_weight).ToStdString(); } - } else { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("print is null!"); - } + plate_data_item->is_support_used = print->is_support_used(); + } else { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("print is null!"); + } //parse filament info - plate_data_item->parse_filament_info(m_plate_list[i]->get_slice_result()); - } else { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "slice result = " << m_plate_list[i]->get_slice_result() - << ", result valid = " << m_plate_list[i]->is_slice_result_valid(); - } - } + plate_data_item->parse_filament_info(m_plate_list[i]->get_slice_result()); + } else { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "slice result = " << m_plate_list[i]->get_slice_result() + << ", result valid = " << m_plate_list[i]->is_slice_result_valid(); + } + } } plate_data_list.push_back(plate_data_item); @@ -4229,8 +4234,8 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list) { BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":plate index %1% seems invalid, skip it")% plate_data_list[i]->plate_index; } - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, gcode_file %2%, is_sliced_valid %3%, toolpath_outside %4%") - %i %plate_data_list[i]->gcode_file %plate_data_list[i]->is_sliced_valid %plate_data_list[i]->toolpath_outside; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, gcode_file %2%, is_sliced_valid %3%, toolpath_outside %4%, is_support_used %5%") + %i %plate_data_list[i]->gcode_file %plate_data_list[i]->is_sliced_valid %plate_data_list[i]->toolpath_outside %plate_data_list[i]->is_support_used; //load object and instance from 3mf //just test for file correct or not, we will rebuild later /*for (std::vector>::iterator it = plate_data_list[i]->objects_and_instances.begin(); it != plate_data_list[i]->objects_and_instances.end(); ++it) @@ -4254,8 +4259,11 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list) m_plate_list[index]->slice_filaments_info = plate_data_list[i]->slice_filaments_info; gcode_result->warnings = plate_data_list[i]->warnings; if (m_plater && !plate_data_list[i]->thumbnail_file.empty()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load thumbnail from %2%.")%(i+1) %plate_data_list[i]->thumbnail_file; if (boost::filesystem::exists(plate_data_list[i]->thumbnail_file)) { m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->thumbnail_file); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ <thumbnail_data.width %m_plate_list[index]->thumbnail_data.height %m_plate_list[index]->thumbnail_data.pixels.size(); } }