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
This commit is contained in:
lane.wei 2022-11-14 21:59:49 +08:00 committed by Lane.Wei
parent 0713945e02
commit c431cbf202
6 changed files with 329 additions and 235 deletions

View File

@ -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<size_t, bool> orients_requirement;
std::vector<Preset*> 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="<<bedfs[2].x() - bedfs[0].x()<<",y="<<bedfs[2].y() - bedfs[0].y()<<",z="<< print_height <<"\n";
}
if (plate_data.size() > 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="<<o->id().id<<std::endl;
orientation::orient(o);
oriented_or_arranged = true;
}
else
{
@ -1106,6 +1107,7 @@ int CLI::run(int argc, char **argv)
}
//BBS: clear the orient objects lists
orients_requirement.clear();
oriented_or_arranged |= need_arrange;
if (need_arrange)
{
@ -1532,6 +1534,7 @@ int CLI::run(int argc, char **argv)
}
#endif
bool need_regenerate_thumbnail = oriented_or_arranged;
// get type and color for platedata
auto* filament_types = dynamic_cast<const ConfigOptionStrings*>(m_print_config.option("filament_type"));
const ConfigOptionStrings* filament_color = dynamic_cast<const ConfigOptionStrings *>(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<std::string> colors;
if (filament_color) {
colors= filament_color->vserialize();
}
else
colors.push_back("#FFFFFF");
if (need_regenerate_thumbnail) {
std::vector<std::string> colors;
if (filament_color) {
colors= filament_color->vserialize();
}
else
colors.push_back("#FFFFFF");
std::vector<std::array<float, 4>> 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<std::array<float, 4>> 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 " <<code<< std::endl;
}
else {
BOOST_LOG_TRIVIAL(info) << "glfwInit Success."<< std::endl;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, gl_major);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, gl_minor);
glfwWindowHint(GLFW_RED_BITS, 8);
glfwWindowHint(GLFW_GREEN_BITS, 8);
glfwWindowHint(GLFW_BLUE_BITS, 8);
glfwWindowHint(GLFW_ALPHA_BITS, 8);
glfwWindowHint(GLFW_VISIBLE, false);
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfwDisable(GLFW_AUTO_POLL_EVENTS);
glfwSetErrorCallback(glfw_callback);
int ret = glfwInit();
if (ret == GLFW_FALSE) {
int code = glfwGetError(NULL);
BOOST_LOG_TRIVIAL(error) << "glfwInit return error, code " <<code<< std::endl;
}
else {
BOOST_LOG_TRIVIAL(info) << "glfwInit Success."<< std::endl;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, gl_major);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, gl_minor);
glfwWindowHint(GLFW_RED_BITS, 8);
glfwWindowHint(GLFW_GREEN_BITS, 8);
glfwWindowHint(GLFW_BLUE_BITS, 8);
glfwWindowHint(GLFW_ALPHA_BITS, 8);
glfwWindowHint(GLFW_VISIBLE, false);
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfwDisable(GLFW_AUTO_POLL_EVENTS);
#ifdef __WXMAC__
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#else
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
#endif
#ifdef __linux__
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_OSMESA_CONTEXT_API);
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_OSMESA_CONTEXT_API);
#endif
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);
}
bool opengl_valid = opengl_mgr.init_gl();
if (!opengl_valid) {
BOOST_LOG_TRIVIAL(error) << "init opengl failed! skip thumbnail generating" << std::endl;
}
else {
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<const ConfigOptionInt *>(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<const ConfigOptionInt *>(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<float, 4> 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<const ConfigOptionInt *>(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<const ConfigOptionInt *>(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 *>(print_base);
//don't render calibration picture
/*BuildVolume build_volume(part_plate->get_shape(), print_height);
const std::vector<BoundingBoxf3>& 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<std::string> 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<BBoxData>& id_bboxes = plate_bbox->bbox_objs;
BoundingBoxf bbox_all;
auto seq_print = m_print_config.option<ConfigOptionEnum<PrintSequence>>("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<float, 4> 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 *>(print_base);
//don't render calibration picture
/*BuildVolume build_volume(part_plate->get_shape(), print_height);
const std::vector<BoundingBoxf3>& 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<std::string> 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<BBoxData>& id_bboxes = plate_bbox->bbox_objs;
BoundingBoxf bbox_all;
auto seq_print = m_print_config.option<ConfigOptionEnum<PrintSequence>>("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__)

View File

@ -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++)
{

View File

@ -68,6 +68,7 @@ struct PlateData
std::string gcode_weight;
std::vector<FilamentInfo> slice_filaments_info;
DynamicPrintConfig config;
bool is_support_used {false};
bool is_sliced_valid = false;
bool toolpath_outside {false};

View File

@ -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<std::pair<Polygon, float>>* 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;

View File

@ -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<ApplyStatus>(apply_status);
}

View File

@ -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<size_t>(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<size_t>(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<std::pair<int, int>>::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__ <<boost::format(": plate %1% after load, width %2%, height %3%, size %4%!")
%(i+1) %m_plate_list[index]->thumbnail_data.width %m_plate_list[index]->thumbnail_data.height %m_plate_list[index]->thumbnail_data.pixels.size();
}
}