ENH: thumbnail: add top_view thumbnails and picking thumbnails

1. add top view thumbnail for each plate
2. add picking thumbnails for each plate
3. save model object id for picking

Change-Id: I1d7f6ade22726ff12c282cb12e4a78e6b444a070
This commit is contained in:
lane.wei 2023-03-08 11:27:26 +08:00 committed by Lane.Wei
parent 9f3a89320b
commit c65a5f8bf5
15 changed files with 716 additions and 195 deletions

View File

@ -372,17 +372,18 @@ int CLI::run(int argc, char **argv)
/*BOOST_LOG_TRIVIAL(info) << "begin to setup params, argc=" << argc << std::endl;
for (int index=0; index < argc; index++)
BOOST_LOG_TRIVIAL(info) << "index="<< index <<", arg is "<< argv[index] <<std::endl;
int debug_argc = 5;
int debug_argc = 6;
char *debug_argv[] = {
"E:\work\projects\bambu_release\bamboo_slicer\build_debug\src\Debug\bambu-studio.exe",
"--slice",
"0",
"E:\work\projects\bambu_debug\bamboo_slicer\build_debug\src\Debug\bambu-studio.exe",
"--uptodate",
//"--load-settings",
//"machine.json;process.json",
//"--load-filaments",
//"filament.json",
"--export-3mf=output.3mf",
"test_cube.3mf"
"--slice",
"0",
"Cube2.3mf"
};
if (! this->setup(debug_argc, debug_argv))*/
if (!this->setup(argc, argv))
@ -412,11 +413,13 @@ int CLI::run(int argc, char **argv)
bool translate_old = false;
int current_width, current_depth, current_height;
const std::vector<std::string> &load_configs = m_config.option<ConfigOptionStrings>("load_settings", true)->values;
const std::vector<std::string> &load_configs = m_config.option<ConfigOptionStrings>("load_settings", true)->values;
//BBS: always use ForwardCompatibilitySubstitutionRule::Enable
//const ForwardCompatibilitySubstitutionRule config_substitution_rule = m_config.option<ConfigOptionEnum<ForwardCompatibilitySubstitutionRule>>("config_compatibility", true)->value;
const ForwardCompatibilitySubstitutionRule config_substitution_rule = ForwardCompatibilitySubstitutionRule::Enable;
const std::vector<std::string> &load_filaments = m_config.option<ConfigOptionStrings>("load_filaments", true)->values;
const std::vector<std::string> &load_filaments = m_config.option<ConfigOptionStrings>("load_filaments", true)->values;
const std::vector<int> &skip_objects = m_config.option<ConfigOptionInts>("skip_objects", true)->values;
bool need_skip = (skip_objects.size() > 0)?true:false;
if (start_gui) {
BOOST_LOG_TRIVIAL(info) << "no action, start gui directly" << std::endl;
@ -1029,7 +1032,7 @@ int CLI::run(int argc, char **argv)
boost::nowide::cerr << __FUNCTION__<<": can not found option " <<opt_key<<"from config." <<std::endl;
return CLI_CONFIG_FILE_ERROR;
}
if (opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "model_id" || opt_key == "dev_model_name")
if (opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "model_id" || opt_key == "inherits" ||opt_key == "dev_model_name")
continue;
else {
ConfigOption *dest_opt = full_config.option(opt_key, true);
@ -1209,6 +1212,8 @@ int CLI::run(int argc, char **argv)
}
else
{
if (opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "model_id" || opt_key == "dev_model_name" || opt_key == "filament_settings_id")
continue;
ConfigOption *opt = m_print_config.option(opt_key, true);
if (opt == nullptr) {
// opt_key does not exist in this ConfigBase and it cannot be created, because it is not defined by this->def().
@ -1218,11 +1223,7 @@ int CLI::run(int argc, char **argv)
}
ConfigOptionVectorBase* opt_vec_dst = static_cast<ConfigOptionVectorBase*>(opt);
const ConfigOptionVectorBase* opt_vec_src = static_cast<const ConfigOptionVectorBase*>(source_opt);
if (opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "model_id" || opt_key == "dev_model_name" || opt_key == "filament_settings_id")
continue;
else {
opt_vec_dst->set_at(opt_vec_src, filament_index-1, 0);
}
opt_vec_dst->set_at(opt_vec_src, filament_index-1, 0);
}
}
}
@ -1338,6 +1339,7 @@ int CLI::run(int argc, char **argv)
partplate_list.reset_size(current_width, current_depth, current_height, true, true);
}
}
/*for (ModelObject *model_object : m_models[0].objects)
for (ModelInstance *model_instance : model_object->instances)
{
@ -1804,6 +1806,17 @@ int CLI::run(int argc, char **argv)
if (partplate_list.get_plate_count() == 1)
pre_check = false;
bool finished = false;
//skip model object
std::map<int, bool> skip_maps;
if (need_skip) {
BOOST_LOG_TRIVIAL(info) << boost::format("need to skip objects, size %1%:")%skip_objects.size();
for (int index = 0; index < skip_objects.size(); index++)
{
skip_maps[skip_objects[index]] = false;
BOOST_LOG_TRIVIAL(info) << boost::format("object %1%, id %2%")%index %skip_objects[index];
}
}
/*if (opt_key == "export_gcode" && printer_technology == ptSLA) {
boost::nowide::cerr << "error: cannot export G-code for an FFF configuration" << std::endl;
flush_and_exit(1);
@ -1839,6 +1852,7 @@ int CLI::run(int argc, char **argv)
BOOST_LOG_TRIVIAL(info) << "Skip plate " << index+1 << std::endl;
continue;
}
BOOST_LOG_TRIVIAL(info) << boost::format("Plate %1%: pre_check %2%, start")%(index+1)%pre_check;
long long start_time = 0, end_time = 0;
start_time = (long long)Slic3r::Utils::get_current_time_utc();
//get the current partplate
@ -1863,18 +1877,45 @@ int CLI::run(int argc, char **argv)
% print_volume.min(2) % print_volume.max(0) % print_volume.max(1) % print_volume.max(2) << std::endl;
#else
BuildVolume build_volume(part_plate->get_shape(), print_height);
model.update_print_volume_state(build_volume);
//model.update_print_volume_state(build_volume);
unsigned int count = model.update_print_volume_state(build_volume);
if (count == 0) {
BOOST_LOG_TRIVIAL(error) << "plate "<< index+1<< ": Nothing to be sliced, Either the print is empty or no object is fully inside the print volume before apply." << std::endl;
flush_and_exit(CLI_NO_SUITABLE_OBJECTS);
}
else {
else if ((plate_to_slice != 0) || pre_check) {
long long triangle_count = 0;
int printable_instances = 0;
int skipped_count = 0;
for (ModelObject* model_object : model.objects)
for (ModelInstance *i : model_object->instances)
{
if (skip_maps.find(i->loaded_id) != skip_maps.end()) {
skip_maps[i->loaded_id] = true;
i->printable = false;
if (i->print_volume_state == ModelInstancePVS_Inside) {
skipped_count++;
BOOST_LOG_TRIVIAL(info) << boost::format("Plate %1%: skip object %2%.")%(index+1)%i->loaded_id;
//need to regenerate the thumbnail
if (plate_data_src.size() > index) {
if (!plate_data_src[index]->thumbnail_file.empty()) {
BOOST_LOG_TRIVIAL(info) << boost::format("Plate %1%: clear loaded thumbnail %2%.")%(index+1)%plate_data_src[index]->thumbnail_file;
plate_data_src[index]->thumbnail_file.clear();
}
if (!plate_data_src[index]->top_file.empty()) {
BOOST_LOG_TRIVIAL(info) << boost::format("Plate %1%: clear loaded top_thumbnail %2%.")%(index+1)%plate_data_src[index]->top_file;
plate_data_src[index]->top_file.clear();
}
if (!plate_data_src[index]->pick_file.empty()) {
BOOST_LOG_TRIVIAL(info) << boost::format("Plate %1%: clear loaded pick_thumbnail %2%.")%(index+1)%plate_data_src[index]->pick_file;
plate_data_src[index]->pick_file.clear();
}
}
}
continue;
}
if (i->print_volume_state == ModelInstancePVS_Partly_Outside)
{
BOOST_LOG_TRIVIAL(error) << "plate "<< index+1<< ": Found Object " << model_object->name <<" partly inside, can not be sliced." << std::endl;
@ -1896,7 +1937,15 @@ int CLI::run(int argc, char **argv)
}
}
}
if (i->print_volume_state == ModelInstancePVS_Inside)
printable_instances++;
}
if (printable_instances == 0) {
BOOST_LOG_TRIVIAL(error) << "plate "<< index+1<< ": Nothing to be sliced, after skipping "<<skipped_count<<" objects."<< std::endl;
flush_and_exit(CLI_NO_SUITABLE_OBJECTS_AFTER_SKIP);
}
}
// BBS: TODO
//BOOST_LOG_TRIVIAL(info) << boost::format("print_volume {%1%,%2%,%3%}->{%4%, %5%, %6%}, has %7% printables") % print_volume.min(0) % print_volume.min(1)
@ -2017,7 +2066,7 @@ int CLI::run(int argc, char **argv)
}
}
} catch (const std::exception &ex) {
BOOST_LOG_TRIVIAL(info) << "found slicing or export error for partplate "<<index+1 << std::endl;
BOOST_LOG_TRIVIAL(error) << "found slicing or export error for partplate "<<index+1 << std::endl;
boost::nowide::cerr << ex.what() << std::endl;
//continue;
flush_and_exit(CLI_SLICING_ERROR);
@ -2076,7 +2125,7 @@ int CLI::run(int argc, char **argv)
if (export_to_3mf) {
//BBS: export as bbl 3mf
Slic3r::GUI::OpenGLManager opengl_mgr;
std::vector<ThumbnailData *> thumbnails;
std::vector<ThumbnailData *> thumbnails, top_thumbnails, pick_thumbnails;
std::vector<PlateBBoxData*> plate_bboxes;
PlateDataPtrs plate_data_list;
partplate_list.store_to_3mf_structure(plate_data_list);
@ -2093,6 +2142,9 @@ int CLI::run(int argc, char **argv)
#endif
bool need_regenerate_thumbnail = oriented_or_arranged;
bool need_regenerate_top_thumbnail = oriented_or_arranged;
bool need_create_thumbnail_group = false, need_create_top_group = false;
// 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"));
@ -2100,6 +2152,8 @@ int CLI::run(int argc, char **argv)
for (int i = 0; i < plate_data_list.size(); i++) {
PlateData *plate_data = plate_data_list[i];
bool skip_this_plate = ((plate_to_slice != 0) && (plate_to_slice != (i + 1)))?true:false;
for (auto it = plate_data->slice_filaments_info.begin(); it != plate_data->slice_filaments_info.end(); it++) {
//it->filament_id = filament_id?filament_id->get_at(it->id):"unknown";
std::string display_filament_type;
@ -2113,15 +2167,41 @@ int CLI::run(int argc, char **argv)
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;
if (!skip_this_plate) {
need_regenerate_thumbnail = true;
need_create_thumbnail_group = true;
}
}
else {
BOOST_LOG_TRIVIAL(info) << boost::format("thumbnails stage: plate %1%'s thumbnail file exists, no need to regenerate")%(i+1);
}
}
else {
if (!skip_this_plate) {
need_create_thumbnail_group = true;
}
}
if (plate_data->top_file.empty() || plate_data->pick_file.empty()) {
if (plate_data_src.size() > i) {
plate_data->top_file = plate_data_src[i]->top_file;
plate_data->pick_file = plate_data_src[i]->pick_file;
}
if (plate_data->top_file.empty()|| plate_data->pick_file.empty()
|| (!boost::filesystem::exists(plate_data->top_file)) || (!boost::filesystem::exists(plate_data->pick_file))) {
BOOST_LOG_TRIVIAL(info) << boost::format("thumbnails stage: plate %1%'s top_file %2% also not there, need to regenerate")%(i+1)%plate_data->top_file;
if (!skip_this_plate) {
need_regenerate_top_thumbnail = true;
need_create_top_group = true;
}
}
else {
BOOST_LOG_TRIVIAL(info) << boost::format("thumbnails stage: plate %1%'s top_thumbnail file exists, no need to regenerate")%(i+1);
}
}
}
if (need_regenerate_thumbnail) {
if (need_regenerate_thumbnail || need_regenerate_top_thumbnail) {
std::vector<std::string> colors;
if (filament_color) {
colors= filament_color->vserialize();
@ -2199,7 +2279,7 @@ int CLI::run(int argc, char **argv)
// 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.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, "volume", true, false, true);
//glvolume_collection.volumes.back()->geometry_id = key.geometry_id;
std::string color = filament_color?filament_color->get_at(extruder_id - 1):"#00FF00";
@ -2213,6 +2293,7 @@ int CLI::run(int argc, char **argv)
new_color[2] = float(rgb_color[2]) / 255.f;
new_color[3] = 1.f;
glvolume_collection.volumes.back()->set_color(new_color);
glvolume_collection.volumes.back()->printable = model_instance.printable;
}
}
}
@ -2227,39 +2308,145 @@ int CLI::run(int argc, char **argv)
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;
if ((plate_to_slice != 0) && (plate_to_slice != (i + 1))) {
BOOST_LOG_TRIVIAL(info) << boost::format("Line %1%: regenerate thumbnail, reset plate %2%'s thumbnail.")%__LINE__%(i+1);
plate_data->plate_thumbnail.reset();
}
else
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;
}
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s thumbnail, need to regenerate")%(i+1);
ThumbnailData * thumbnail_data = new ThumbnailData();
unsigned int thumbnail_width = 512, thumbnail_height = 512;
const ThumbnailsParams thumbnail_params = {{}, false, true, true, true, i};
switch (Slic3r::GUI::OpenGLManager::get_framebuffers_type())
else if (!plate_data->thumbnail_file.empty() && (boost::filesystem::exists(plate_data->thumbnail_file)))
{
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;
if ((plate_to_slice != 0) && (plate_to_slice != (i + 1))) {
BOOST_LOG_TRIVIAL(info) << boost::format("Line %1%: regenerate thumbnail, clear plate %2%'s thumbnail file path to empty.")%__LINE__%(i+1);
plate_data->thumbnail_file.clear();
}
else
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1% has a valid thumbnail %2% extracted from 3mf, directly using it")%(i+1) %plate_data->thumbnail_file;
}
else {
ThumbnailData* thumbnail_data = &plate_data->plate_thumbnail;
if ((plate_to_slice != 0) && (plate_to_slice != (i + 1))) {
BOOST_LOG_TRIVIAL(info) << boost::format("Line %1%: regenerate thumbnail, Skip plate %2%.")%__LINE__%(i+1);
}
else {
unsigned int thumbnail_width = 512, thumbnail_height = 512;
const ThumbnailsParams thumbnail_params = {{}, false, true, true, true, i};
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s thumbnail, need to regenerate")%(i+1);
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;
}
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s thumbnail,finished rendering")%(i+1);
}
}
if (need_create_thumbnail_group) {
thumbnails.push_back(&plate_data->plate_thumbnail);
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%: add thumbnail data into group")%(i+1);
}
//top thumbnails
/*if (part_plate->top_thumbnail_data.is_valid() && part_plate->pick_thumbnail_data.is_valid()) {
if ((plate_to_slice != 0) && (plate_to_slice != (i + 1))) {
BOOST_LOG_TRIVIAL(info) << boost::format("Line %1%: regenerate thumbnail, reset plate %2%'s top/pick thumbnail.")%__LINE__%(i+1);
part_plate->top_thumbnail_data.reset();
part_plate->pick_thumbnail_data.reset();
plate_data->top_file.clear();
plate_data->pick_file.clear();
}
else {
plate_data->top_file = "valid_top";
plate_data->pick_file = "valid_pick";
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1% has a valid top/pick thumbnail data, directly using it")%(i+1);
}
}
else*/
if ((!plate_data->top_file.empty() && (boost::filesystem::exists(plate_data->top_file)))
&&(!plate_data->pick_file.empty() && (boost::filesystem::exists(plate_data->pick_file))))
{
if ((plate_to_slice != 0) && (plate_to_slice != (i + 1))) {
BOOST_LOG_TRIVIAL(info) << boost::format("Line %1%: regenerate thumbnail, clear plate %2%'s top/pick thumbnail file path to empty.")%__LINE__%(i+1);
plate_data->top_file.clear();
plate_data->pick_file.clear();
}
else
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1% has valid top/pick thumbnail extracted from 3mf, directly using it")%(i+1);
}
else{
ThumbnailData* top_thumbnail = &part_plate->top_thumbnail_data;
ThumbnailData* picking_thumbnail = &part_plate->pick_thumbnail_data;
if ((plate_to_slice != 0) && (plate_to_slice != (i + 1))) {
BOOST_LOG_TRIVIAL(info) << boost::format("Line %1%: regenerate thumbnail, Skip plate %2%.")%__LINE__%(i+1);
part_plate->top_thumbnail_data.reset();
part_plate->pick_thumbnail_data.reset();
plate_data->top_file.clear();
plate_data->pick_file.clear();
}
else {
unsigned int thumbnail_width = 512, thumbnail_height = 512;
const ThumbnailsParams thumbnail_params = { {}, false, true, false, true, i };
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s top/pick thumbnail missed, need to regenerate")%(i+1);
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(*top_thumbnail,
thumbnail_width, thumbnail_height, thumbnail_params,
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, false);
Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer(*picking_thumbnail,
thumbnail_width, thumbnail_height, thumbnail_params,
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, true);
break;
}
case Slic3r::GUI::OpenGLManager::EFramebufferType::Ext:
{
BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: EXT");
Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer_ext(*top_thumbnail,
thumbnail_width, thumbnail_height, thumbnail_params,
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, false);
Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer_ext(*picking_thumbnail,
thumbnail_width, thumbnail_height, thumbnail_params,
partplate_list, model.objects, glvolume_collection, colors_out, shader, Slic3r::GUI::Camera::EType::Ortho, true, true);
break;
}
default:
BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: unknown");
break;
}
plate_data->top_file = "valid_top";
plate_data->pick_file = "valid_pick";
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s top_thumbnail,finished rendering")%(i+1);
}
}
if (need_create_top_group) {
top_thumbnails.push_back(&part_plate->top_thumbnail_data);
pick_thumbnails.push_back(&part_plate->pick_thumbnail_data);
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%: add thumbnail data for top and pick into group")%(i+1);
}
thumbnails.push_back(thumbnail_data);
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s thumbnail,finished rendering")%(i+1);
}
}
}
@ -2267,17 +2454,42 @@ int CLI::run(int argc, char **argv)
glfwTerminate();
}
else {
BOOST_LOG_TRIVIAL(info) << boost::format("use previous thumbnails, no need to regenerate");
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()) {
bool skip_this_plate = ((plate_to_slice != 0) && (plate_to_slice != (i + 1)))?true:false;
Slic3r::GUI::PartPlate *part_plate = partplate_list.get_plate(i);
if (skip_this_plate) {
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%'s all the thumbnails skipped, reset here")%(i+1);
plate_data->plate_thumbnail.reset();
plate_data->thumbnail_file.clear();
part_plate->top_thumbnail_data.reset();
part_plate->pick_thumbnail_data.reset();
plate_data->top_file.clear();
plate_data->pick_file.clear();
}
if (need_create_thumbnail_group) {
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;
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%: add thumbnail data into group")%(i+1);
}
if (need_create_top_group) {
top_thumbnails.push_back(&part_plate->top_thumbnail_data);
pick_thumbnails.push_back(&part_plate->pick_thumbnail_data);
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%: add thumbnail data for top and pick into group")%(i+1);
}
}
}
//generate first layer bboxes
for (int i = 0; i < partplate_list.get_plate_count(); i++) {
if ((plate_to_slice != 0) && (plate_to_slice != (i + 1))) {
BOOST_LOG_TRIVIAL(info) << boost::format("Line %1%: generate bbox, Skip plate %2%.")%__LINE__%(i+1);
plate_bboxes.push_back(new PlateBBoxData());
continue;
}
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()) {
@ -2403,14 +2615,19 @@ int CLI::run(int argc, char **argv)
#endif
BOOST_LOG_TRIVIAL(info) << "will export 3mf to " << export_3mf_file << std::endl;
if (! this->export_project(&m_models[0], export_3mf_file, plate_data_list, project_presets, thumbnails, calibration_thumbnails, plate_bboxes, &m_print_config))
if (! this->export_project(&m_models[0], export_3mf_file, plate_data_list, project_presets, thumbnails, top_thumbnails, pick_thumbnails,
calibration_thumbnails, plate_bboxes, &m_print_config))
{
release_PlateData_list(plate_data_list);
flush_and_exit(CLI_EXPORT_3MF_ERROR);
}
release_PlateData_list(plate_data_list);
for (unsigned int i = 0; i < thumbnails.size(); i++)
delete thumbnails[i];
thumbnails[i]->reset();
for (unsigned int i = 0; i < top_thumbnails.size(); i++)
top_thumbnails[i]->reset();
for (unsigned int i = 0; i < pick_thumbnails.size(); i++)
pick_thumbnails[i]->reset();
for (unsigned int i = 0; i < calibration_thumbnails.size(); i++)
delete calibration_thumbnails[i];
@ -2589,7 +2806,8 @@ bool CLI::export_models(IO::ExportFormat format)
//BBS: add export_project function
bool CLI::export_project(Model *model, std::string& path, PlateDataPtrs &partplate_data,
std::vector<Preset*>& project_presets, std::vector<ThumbnailData*>& thumbnails, std::vector<ThumbnailData*>& calibration_thumbnails, std::vector<PlateBBoxData*>& plate_bboxes, const DynamicPrintConfig* config)
std::vector<Preset*>& project_presets, std::vector<ThumbnailData*>& thumbnails, std::vector<ThumbnailData*>& top_thumbnails, std::vector<ThumbnailData*>& pick_thumbnails,
std::vector<ThumbnailData*>& calibration_thumbnails, std::vector<PlateBBoxData*>& plate_bboxes, const DynamicPrintConfig* config)
{
//const std::string path = this->output_filepath(*model, IO::TMF);
bool success = false;
@ -2601,9 +2819,11 @@ bool CLI::export_project(Model *model, std::string& path, PlateDataPtrs &partpla
store_params.project_presets = project_presets;
store_params.config = (DynamicPrintConfig*)config;
store_params.thumbnail_data = thumbnails;
store_params.top_thumbnail_data = top_thumbnails;
store_params.pick_thumbnail_data = pick_thumbnails;
store_params.calibration_thumbnail_data = calibration_thumbnails;
store_params.id_bboxes = plate_bboxes;
store_params.strategy = SaveStrategy::Silence|SaveStrategy::WithGcode|SaveStrategy::SplitModel;
store_params.strategy = SaveStrategy::Silence|SaveStrategy::WithGcode|SaveStrategy::SplitModel|SaveStrategy::UseLoadedId;
success = Slic3r::store_bbs_3mf(store_params);

View File

@ -39,7 +39,8 @@ private:
bool export_models(IO::ExportFormat format);
//BBS: add export_project function
bool export_project(Model *model, std::string& path, PlateDataPtrs &partplate_data, std::vector<Preset*>& project_presets,
std::vector<ThumbnailData*>& thumbnails, std::vector<ThumbnailData*>& calibration_thumbnails,
std::vector<ThumbnailData*>& thumbnails, std::vector<ThumbnailData*>& top_thumbnails, std::vector<ThumbnailData*>& pick_thumbnails,
std::vector<ThumbnailData*>& calibration_thumbnails,
std::vector<PlateBBoxData*>& plate_bboxes, const DynamicPrintConfig* config);
bool has_print_action() const { return m_config.opt_bool("export_gcode") || m_config.opt_bool("export_sla"); }

View File

@ -250,11 +250,13 @@ static constexpr const char* BED_TYPE_ATTR = "bed_type";
static constexpr const char* PRINT_SEQUENCE_ATTR = "print_sequence";
static constexpr const char* GCODE_FILE_ATTR = "gcode_file";
static constexpr const char* THUMBNAIL_FILE_ATTR = "thumbnail_file";
static constexpr const char* TOP_FILE_ATTR = "top_file";
static constexpr const char* PICK_FILE_ATTR = "pick_file";
static constexpr const char* PATTERN_FILE_ATTR = "pattern_file";
static constexpr const char* PATTERN_BBOX_FILE_ATTR = "pattern_bbox_file";
static constexpr const char* OBJECT_ID_ATTR = "object_id";
static constexpr const char* INSTANCEID_ATTR = "instance_id";
static constexpr const char* ARRANGE_ORDER_ATTR = "arrange_order";
static constexpr const char* IDENTIFYID_ATTR = "identify_id";
static constexpr const char* PLATERID_ATTR = "plater_id";
static constexpr const char* PLATE_IDX_ATTR = "index";
static constexpr const char* SLICE_PREDICTION_ATTR = "prediction";
@ -614,7 +616,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
{
int object_id;
int instance_id;
int arrange_order;
int identify_id;
};
struct Instance
@ -859,7 +861,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
std::string m_Profile_description;
std::string m_profile_user_id;
std::string m_profile_user_name;
XML_Parser m_xml_parser;
// Error code returned by the application side of the parser. In that case the expat may not reliably deliver the error state
// after returning from XML_Parse() function, thus we keep the error state here.
@ -1139,7 +1141,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
m_plater_data.clear();
m_curr_instance.object_id = -1;
m_curr_instance.instance_id = -1;
m_curr_instance.arrange_order = 0;
m_curr_instance.identify_id = 0;
clear_errors();
// restore
@ -1794,12 +1796,15 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
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_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]->top_file = (m_load_restore || it->second->top_file.empty()) ? it->second->top_file : m_backup_path + "/" + it->second->top_file;
plate_data_list[it->first-1]->pick_file = (m_load_restore || it->second->pick_file.empty()) ? it->second->pick_file : m_backup_path + "/" + it->second->pick_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;
current_plate_data = plate_data_list[it->first - 1];
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", plate %1%, thumbnail_file=%2%")%it->first %plate_data_list[it->first-1]->thumbnail_file;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", top_thumbnail_file=%1%, pick_thumbnail_file=%2%")%plate_data_list[it->first-1]->top_file %plate_data_list[it->first-1]->pick_file;
it++;
//update the arrange order
@ -1835,7 +1840,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
continue;
}
ModelInstance* inst = obj->instances[inst_index];
inst->arrange_order = map_it->second.second;
inst->loaded_id = map_it->second.second;
map_it++;
}
}
@ -3525,10 +3530,18 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
{
m_curr_plater->thumbnail_file = value;
}
else if (key == PATTERN_FILE_ATTR)
else if (key == TOP_FILE_ATTR)
{
m_curr_plater->pattern_file = value;
m_curr_plater->top_file = value;
}
else if (key == PICK_FILE_ATTR)
{
m_curr_plater->pick_file = value;
}
//else if (key == PATTERN_FILE_ATTR)
//{
// m_curr_plater->pattern_file = value;
//}
else if (key == PATTERN_BBOX_FILE_ATTR)
{
m_curr_plater->pattern_bbox_file = value;
@ -3537,9 +3550,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
{
m_curr_instance.instance_id = atoi(value.c_str());
}
else if (key == ARRANGE_ORDER_ATTR)
else if (key == IDENTIFYID_ATTR)
{
m_curr_instance.arrange_order = atoi(value.c_str());
m_curr_instance.identify_id = atoi(value.c_str());
}
else if (key == OBJECT_ID_ATTR)
{
@ -3694,13 +3707,13 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
//add_error("invalid object id/instance id");
//skip this instance
m_curr_instance.object_id = m_curr_instance.instance_id = -1;
m_curr_instance.arrange_order = 0;
m_curr_instance.identify_id = 0;
return true;
}
m_curr_plater->obj_inst_map.emplace(m_curr_instance.object_id, std::make_pair(m_curr_instance.instance_id, m_curr_instance.arrange_order));
m_curr_plater->obj_inst_map.emplace(m_curr_instance.object_id, std::make_pair(m_curr_instance.instance_id, m_curr_instance.identify_id));
m_curr_instance.object_id = m_curr_instance.instance_id = -1;
m_curr_instance.arrange_order = 0;
m_curr_instance.identify_id = 0;
return true;
}
@ -4744,6 +4757,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
bool m_save_gcode { false }; // whether to save gcode for normal save
bool m_skip_model { false }; // skip model when exporting .gcode.3mf
bool m_skip_auxiliary { false }; // skip normal axuiliary files
bool m_use_loaded_id { false }; // whether to use loaded id for identify_id
public:
//BBS: add plate data related logic
@ -4762,6 +4776,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
std::vector<Preset*>& project_presets,
const DynamicPrintConfig* config,
const std::vector<ThumbnailData*>& thumbnail_data,
const std::vector<ThumbnailData*>& top_thumbnail_data,
const std::vector<ThumbnailData*>& pick_thumbnail_data,
Export3mfProgressFn proFn,
const std::vector<ThumbnailData*>& calibration_data,
const std::vector<PlateBBoxData*>& id_bboxes,
@ -4772,7 +4788,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
bool _add_content_types_file_to_archive(mz_zip_archive& archive);
bool _add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, int index);
bool _add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, const char* local_path, int index);
bool _add_calibration_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, int index);
bool _add_bbox_file_to_archive(mz_zip_archive& archive, const PlateBBoxData& id_bboxes, int index);
bool _add_relationships_file_to_archive(mz_zip_archive & archive,
@ -4795,7 +4811,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
bool _add_project_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config, Model& model);
//BBS: add project embedded preset files
bool _add_project_embedded_presets_to_archive(mz_zip_archive& archive, Model& model, std::vector<Preset*> project_presets);
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx = -1, bool save_gcode = true);
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx = -1, bool save_gcode = true, bool use_loaded_id = false);
bool _add_slice_info_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list);
bool _add_gcode_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, Export3mfProgressFn proFn = nullptr);
bool _add_custom_gcode_per_print_z_file_to_archive(mz_zip_archive& archive, Model& model, const DynamicPrintConfig* config);
@ -4829,12 +4845,15 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
m_skip_model = store_params.strategy & SaveStrategy::SkipModel;
m_skip_auxiliary = store_params.strategy & SaveStrategy::SkipAuxiliary;
m_use_loaded_id = store_params.strategy & SaveStrategy::UseLoadedId;
boost::system::error_code ec;
std::string filename = std::string(store_params.path);
boost::filesystem::remove(filename + ".tmp", ec);
bool result = _save_model_to_file(filename + ".tmp", *store_params.model, store_params.plate_data_list, store_params.project_presets, store_params.config,
store_params.thumbnail_data, store_params.proFn, store_params.calibration_thumbnail_data, store_params.id_bboxes, store_params.project, store_params.export_plate_idx);
store_params.thumbnail_data, store_params.top_thumbnail_data, store_params.pick_thumbnail_data, store_params.proFn,
store_params.calibration_thumbnail_data, store_params.id_bboxes, store_params.project, store_params.export_plate_idx);
if (result) {
boost::filesystem::rename(filename + ".tmp", filename, ec);
if (ec) {
@ -4902,6 +4921,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
std::vector<Preset*>& project_presets,
const DynamicPrintConfig* config,
const std::vector<ThumbnailData*>& thumbnail_data,
const std::vector<ThumbnailData*>& top_thumbnail_data,
const std::vector<ThumbnailData*>& pick_thumbnail_data,
Export3mfProgressFn proFn,
const std::vector<ThumbnailData*>& calibration_data,
const std::vector<PlateBBoxData*>& id_bboxes,
@ -4916,7 +4937,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
bool cb_cancel = false;
//BBS progress point
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",before open zip writer, m_skip_static %1%, m_save_gcode %2%\n")%m_skip_static %m_save_gcode;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ <<
boost::format(",before open zip writer, m_skip_static %1%, m_save_gcode %2%, m_use_loaded_id %3%")%m_skip_static %m_save_gcode %m_use_loaded_id;
if (proFn) {
proFn(EXPORT_STAGE_OPEN_3MF, 0, 1, cb_cancel);
if (cb_cancel)
@ -4955,43 +4977,115 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
//BBS progress point
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(",before add thumbnails, count %1%\n") % thumbnail_data.size();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(",before add thumbnails, count %1%") % thumbnail_data.size();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",top&&pick thumbnails, count %1%")%top_thumbnail_data.size();
//BBS: add thumbnail for each plate
if (!m_skip_static && thumbnail_data.size() > 0) {
// Adds the file Metadata/thumbnail.png.
if (!m_skip_static) {
std::vector<bool> thumbnail_status(plate_data_list.size(), false);
std::vector<bool> top_thumbnail_status(plate_data_list.size(), false);
std::vector<bool> pick_thumbnail_status(plate_data_list.size(), false);
if ((thumbnail_data.size() > 0)&&(thumbnail_data.size() > plate_data_list.size())) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", thumbnail_data size %1% > plate count %2%")
% thumbnail_data.size() %plate_data_list.size();
return false;
}
if ((top_thumbnail_data.size() > 0)&&(top_thumbnail_data.size() > plate_data_list.size())) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", top_thumbnail_data size %1% > plate count %2%")
% top_thumbnail_data.size() %plate_data_list.size();
return false;
}
if ((pick_thumbnail_data.size() > 0)&&(pick_thumbnail_data.size() > plate_data_list.size())) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", pick_thumbnail_data size %1% > plate count %2%")
% pick_thumbnail_data.size() %plate_data_list.size();
return false;
}
if (top_thumbnail_data.size() != pick_thumbnail_data.size()) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", top_thumbnail_data size %1% != pick_thumbnail_data size %2%")
% top_thumbnail_data.size() %pick_thumbnail_data.size();
return false;
}
if (proFn) {
proFn(EXPORT_STAGE_ADD_THUMBNAILS, 0, plate_data_list.size(), cb_cancel);
if (cb_cancel)
return false;
}
for (unsigned int index = 0; index < thumbnail_data.size(); index++)
{
if (proFn) {
proFn(EXPORT_STAGE_ADD_THUMBNAILS, index, thumbnail_data.size(), cb_cancel);
if (cb_cancel)
return false;
}
if (thumbnail_data[index]->is_valid())
{
if (!_add_thumbnail_file_to_archive(archive, *thumbnail_data[index], index)) {
if (!_add_thumbnail_file_to_archive(archive, *thumbnail_data[index], "Metadata/plate", index)) {
return false;
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",add thumbnail %1%'s data into 3mf")%(index+1);
thumbnail_status[index] = true;
}
}
}
else if (!m_skip_static && plate_data_list.size() > 0) {
// Adds the file Metadata/top_i.png and Metadata/pick_i.png
for (unsigned int index = 0; index < top_thumbnail_data.size(); index++)
{
if (top_thumbnail_data[index]->is_valid())
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",add top thumbnail %1%'s data into 3mf")%(index+1);
if (!_add_thumbnail_file_to_archive(archive, *top_thumbnail_data[index], "Metadata/top", index)) {
return false;
}
top_thumbnail_status[index] = true;
}
if (pick_thumbnail_data[index]->is_valid())
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",add pick thumbnail %1%'s data into 3mf")%(index+1);
if (!_add_thumbnail_file_to_archive(archive, *pick_thumbnail_data[index], "Metadata/pick", index)) {
return false;
}
pick_thumbnail_status[index] = true;
}
}
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))){
if (!thumbnail_status[i] && !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();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(", add thumbnail %1% from file %2%") % (i+1) %plate_data->thumbnail_file;
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;
}
}
if (!top_thumbnail_status[i] && !plate_data->top_file.empty() && (boost::filesystem::exists(plate_data->top_file))){
std::string dst_in_3mf = (boost::format("Metadata/top_%1%.png") % (i + 1)).str();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(", add top thumbnail %1% from file %2%") % (i+1) %plate_data->top_file;
if (!_add_file_to_archive(archive, dst_in_3mf, plate_data->top_file)) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", add top thumbnail %1% failed") % (i+1);
return false;
}
top_thumbnail_status[i] = true;
}
if (!pick_thumbnail_status[i] && !plate_data->pick_file.empty() && (boost::filesystem::exists(plate_data->pick_file))){
std::string dst_in_3mf = (boost::format("Metadata/pick_%1%.png") % (i + 1)).str();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(", add pick thumbnail %1% from file %2%") % (i+1) %plate_data->pick_file;
if (!_add_file_to_archive(archive, dst_in_3mf, plate_data->pick_file)) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", add pick thumbnail %1% failed") % (i+1);
return false;
}
pick_thumbnail_status[i] = true;
}
}
if (proFn) {
proFn(EXPORT_STAGE_ADD_THUMBNAILS, plate_data_list.size(), plate_data_list.size(), cb_cancel);
if (cb_cancel)
return false;
}
}
@ -5183,7 +5277,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
// This file contains all the attributes of all ModelObjects and their ModelVolumes (names, parameter overrides).
// As there is just a single Indexed Triangle Set data stored per ModelObject, offsets of volumes into their respective Indexed Triangle Set data
// is stored here as well.
if (!_add_model_config_file_to_archive(archive, model, plate_data_list, objects_data, export_plate_idx, m_save_gcode)) {
if (!_add_model_config_file_to_archive(archive, model, plate_data_list, objects_data, export_plate_idx, m_save_gcode, m_use_loaded_id)) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", _add_model_config_file_to_archive failed\n");
return false;
}
@ -5295,14 +5389,14 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
return true;
}
bool _BBS_3MF_Exporter::_add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, int index)
bool _BBS_3MF_Exporter::_add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, const char* local_path, int index)
{
bool res = false;
size_t png_size = 0;
void* png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)thumbnail_data.pixels.data(), thumbnail_data.width, thumbnail_data.height, 4, &png_size, MZ_DEFAULT_COMPRESSION, 1);
if (png_data != nullptr) {
std::string thumbnail_name = (boost::format("Metadata/plate_%1%.png") % (index + 1)).str();
std::string thumbnail_name = (boost::format("%1%_%2%.png")%local_path % (index + 1)).str();
res = mz_zip_writer_add_mem(&archive, thumbnail_name.c_str(), (const void*)png_data, png_size, MZ_NO_COMPRESSION);
mz_free(png_data);
}
@ -5319,7 +5413,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
{
bool res = false;
size_t png_size = 0;
/*size_t png_size = 0;
void* png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)thumbnail_data.pixels.data(), thumbnail_data.width, thumbnail_data.height, 4, &png_size, MZ_DEFAULT_COMPRESSION, 1);
if (png_data != nullptr) {
std::string thumbnail_name = (boost::format(PATTERN_FILE_FORMAT) % (index + 1)).str();
@ -5330,7 +5424,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
if (!res) {
add_error("Unable to add thumbnail file to archive");
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", Unable to add thumbnail file to archive\n");
}
}*/
return res;
}
@ -6332,7 +6426,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
return true;
}
bool _BBS_3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx, bool save_gcode)
bool _BBS_3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx, bool save_gcode, bool use_loaded_id)
{
std::stringstream stream;
std::map<const TriangleMesh*, int> shared_meshes;
@ -6493,10 +6587,20 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << THUMBNAIL_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << thumbnail_file_in_3mf << "\"/>\n";
}
if (!plate_data->pattern_file.empty()) {
if (!plate_data->top_file.empty()) {
std::string top_file_in_3mf = (boost::format(TOP_FILE_FORMAT) % (plate_data->plate_index + 1)).str();
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << TOP_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << top_file_in_3mf << "\"/>\n";
}
if (!plate_data->pick_file.empty()) {
std::string pick_file_in_3mf = (boost::format(PICK_FILE_FORMAT) % (plate_data->plate_index + 1)).str();
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PICK_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << pick_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();
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PATTERN_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << pattern_file_in_3mf << "\"/>\n";
}
}*/
if (!plate_data->pattern_bbox_file.empty()) {
std::string pattern_bbox_file_in_3mf = (boost::format(PATTERN_CONFIG_FILE_FORMAT) % (plate_data->plate_index + 1)).str();
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PATTERN_BBOX_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << pattern_bbox_file_in_3mf << "\"/>\n";
@ -6509,7 +6613,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
stream << " <" << INSTANCE_TAG << ">\n";
int obj_id = plate_data->objects_and_instances[j].first;
int inst_id = plate_data->objects_and_instances[j].second;
int arrange_o = 0;
int identify_id = 0;
ModelObject* obj = NULL;
ModelInstance* inst = NULL;
if (obj_id >= model.objects.size()) {
@ -6523,7 +6627,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
else if (obj){
inst = obj->instances[inst_id];
arrange_o = inst->arrange_order;
if (use_loaded_id && (inst->loaded_id > 0))
identify_id = inst->loaded_id;
else
identify_id = inst->id().id;
}
if (m_skip_static && obj) {
obj_id = obj->get_backup_id();
@ -6534,7 +6641,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << OBJECT_ID_ATTR << "\" " << VALUE_ATTR << "=\"" << obj_id << "\"/>\n";
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << INSTANCEID_ATTR << "\" " << VALUE_ATTR << "=\"" << inst_id << "\"/>\n";
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << ARRANGE_ORDER_ATTR << "\" " << VALUE_ATTR << "=\"" << arrange_o << "\"/>\n";
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << IDENTIFYID_ATTR << "\" " << VALUE_ATTR << "=\"" << identify_id << "\"/>\n";
stream << " </" << INSTANCE_TAG << ">\n";
}
}

View File

@ -16,7 +16,9 @@ struct ThumbnailData;
#define GCODE_FILE_FORMAT "Metadata/plate_%1%.gcode"
#define THUMBNAIL_FILE_FORMAT "Metadata/plate_%1%.png"
#define PATTERN_FILE_FORMAT "Metadata/plate_%1%_pattern_layer_0.png"
#define TOP_FILE_FORMAT "Metadata/top_%1%.png"
#define PICK_FILE_FORMAT "Metadata/pick_%1%.png"
//#define PATTERN_FILE_FORMAT "Metadata/plate_%1%_pattern_layer_0.png"
#define PATTERN_CONFIG_FILE_FORMAT "Metadata/plate_%1%.json"
#define EMBEDDED_PRINT_FILE_FORMAT "Metadata/process_settings_%1%.config"
#define EMBEDDED_FILAMENT_FILE_FORMAT "Metadata/filament_settings_%1%.config"
@ -65,8 +67,10 @@ struct PlateData
std::string gcode_file_md5;
std::string thumbnail_file;
ThumbnailData plate_thumbnail;
ThumbnailData pattern_thumbnail;
std::string pattern_file;
std::string top_file;
std::string pick_file;
//ThumbnailData pattern_thumbnail;
//std::string pattern_file;
std::string pattern_bbox_file;
std::string gcode_prediction;
std::string gcode_weight;
@ -102,6 +106,7 @@ enum class SaveStrategy
SkipModel = 1 << 7,
WithSliceInfo = 1 << 8,
SkipAuxiliary = 1 << 9,
UseLoadedId = 1 << 10,
SplitModel = 0x1000 | ProductionExt,
Encrypted = SecureContentExt | SplitModel,
@ -194,6 +199,8 @@ struct StoreParams
std::vector<Preset*> project_presets;
DynamicPrintConfig* config;
std::vector<ThumbnailData*> thumbnail_data;
std::vector<ThumbnailData*> top_thumbnail_data;
std::vector<ThumbnailData*> pick_thumbnail_data;
std::vector<ThumbnailData*> calibration_thumbnail_data;
SaveStrategy strategy = SaveStrategy::Zip64;
Export3mfProgressFn proFn = nullptr;

View File

@ -1070,6 +1070,7 @@ public:
// Whether or not this instance is printable
bool printable;
int arrange_order = 0; // BBS
size_t loaded_id = 0; // BBS
ModelObject* get_object() const { return this->object; }
@ -1262,7 +1263,7 @@ class ModelProfileInfo
{
public:
std::string ProfileTile;
std::string ProfileCover;
std::string ProfileCover;
std::string ProfileDescription;
std::string ProfileUserId;
std::string ProfileUserName;

View File

@ -1442,14 +1442,20 @@ void Print::process(bool use_cache)
for (int index = 0; index < object_count; index++)
{
PrintObject *obj = m_objects[index];
bool found_shared = false;
if (need_slicing_objects.find(obj) == need_slicing_objects.end()) {
for (PrintObject *slicing_obj : need_slicing_objects)
{
if (is_print_object_the_same(obj, slicing_obj)) {
obj->set_shared_object(slicing_obj);
found_shared = true;
break;
}
}
if (!found_shared) {
BOOST_LOG_TRIVIAL(error) << boost::format("Also can not find the shared object, identify_id %1%")%obj->model_object()->instances[0]->loaded_id;
throw Slic3r::SlicingError("Can not find the cached data.");
}
}
}
}
@ -2207,7 +2213,7 @@ std::string PrintStatistics::finalize_output_path(const std::string &path_in) co
#define JSON_EXPOLYGON "expolygon"
#define JSON_ARC_FITTING "arc_fitting"
#define JSON_OBJECT_NAME "name"
#define JSON_ARRANGE_ORDER "arrange_order"
#define JSON_IDENTIFY_ID "identify_id"
#define JSON_LAYERS "layers"
@ -2943,18 +2949,19 @@ int Print::export_cached_data(const std::string& directory, bool with_space)
BOOST_LOG_TRIVIAL(info) << boost::format("shared object %1%, skip directly")%model_obj->name;
continue;
}
BOOST_LOG_TRIVIAL(info) << boost::format("begin to dump object %1%")%model_obj->name;
const PrintInstance &print_instance = obj->instances()[0];
const ModelInstance *model_instance = print_instance.model_instance;
int arrange_order = model_instance->arrange_order;
std::string file_name = directory +"/obj_"+std::to_string(arrange_order)+".json";
size_t identify_id = (model_instance->loaded_id > 0)?model_instance->loaded_id: model_instance->id().id;
std::string file_name = directory +"/obj_"+std::to_string(identify_id)+".json";
BOOST_LOG_TRIVIAL(info) << boost::format("begin to dump object %1%, identify_id %2% to %3%")%model_obj->name %identify_id %file_name;
try {
json root_json, layers_json = json::array(), support_layers_json = json::array();
root_json[JSON_OBJECT_NAME] = model_obj->name;
root_json[JSON_ARRANGE_ORDER] = arrange_order;
root_json[JSON_IDENTIFY_ID] = identify_id;
//export the layers
std::vector<json> layers_json_vector(obj->layer_count());
@ -3139,12 +3146,14 @@ int Print::load_cached_data(const std::string& directory)
obj->clear_layers();
obj->clear_support_layers();
int arrange_order = model_instance->arrange_order;
if (arrange_order <= 0) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": object %1% has invalid arrange_order %2%, can not load cached_data")%model_obj->name %arrange_order;
continue;
int identify_id = model_instance->loaded_id;
if (identify_id <= 0) {
//for old 3mf
identify_id = model_instance->id().id;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": object %1%'s loaded_id is 0, need to use the instance_id %2%")%model_obj->name %identify_id;
//continue;
}
std::string file_name = directory +"/obj_"+std::to_string(arrange_order)+".json";
std::string file_name = directory +"/obj_"+std::to_string(identify_id)+".json";
if (!fs::exists(file_name)) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<<boost::format(": file %1% not exist, maybe a shared object, skip it")%file_name;
@ -3188,13 +3197,13 @@ int Print::load_cached_data(const std::string& directory)
//ifs >> root_json;
std::string name = root_json.at(JSON_OBJECT_NAME);
int order = root_json.at(JSON_ARRANGE_ORDER);
int identify_id = root_json.at(JSON_IDENTIFY_ID);
int layer_count = 0, support_layer_count = 0;
layer_count = root_json[JSON_LAYERS].size();
support_layer_count = root_json[JSON_SUPPORT_LAYERS].size();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<<boost::format(":will load %1%, arrange_order %2%, layer_count %3%, support_layer_count %4%")%name %order %layer_count %support_layer_count;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<<boost::format(":will load %1%, identify_id %2%, layer_count %3%, support_layer_count %4%")%name %identify_id %layer_count %support_layer_count;
Layer* previous_layer = NULL;
//create layer and layer regions

View File

@ -4786,6 +4786,12 @@ CLIMiscConfigDef::CLIMiscConfigDef()
def->cli_params = "\"filament1.json;filament2.json;...\"";
def->set_default_value(new ConfigOptionStrings());
def = this->add("skip_objects", coStrings);
def->label = L("Skip Objects");
def->tooltip = L("Skip some objects in this print");
def->cli_params = "\"3;5;10;77\"";
def->set_default_value(new ConfigOptionInts());
/*def = this->add("output", coString);
def->label = L("Output File");
def->tooltip = L("The file where the output will be written (if not specified, it will be based on the input file).");

View File

@ -47,6 +47,7 @@
#define CLI_IMPORT_CACHE_LOAD_FAILED -57
#define CLI_SLICING_TIME_EXCEEDS_LIMIT -58
#define CLI_TRIANGLE_COUNT_EXCEEDS_LIMIT -59
#define CLI_NO_SUITABLE_OBJECTS_AFTER_SKIP -60
#define CLI_SLICING_ERROR -100

View File

@ -1044,7 +1044,8 @@ int GLVolumeCollection::load_object_volume(
int instance_idx,
const std::string &color_by,
bool opengl_initialized,
bool in_assemble_view)
bool in_assemble_view,
bool use_loaded_id)
{
const ModelVolume *model_volume = model_object->volumes[volume_idx];
const int extruder_id = model_volume->extruder_id();
@ -1079,6 +1080,11 @@ int GLVolumeCollection::load_object_volume(
else
v.set_instance_transformation(instance->get_transformation());
v.set_volume_transformation(model_volume->get_transformation());
//use object's instance id
if (use_loaded_id && (instance->loaded_id > 0))
v.model_object_ID = instance->loaded_id;
else
v.model_object_ID = instance->id().id;
return int(this->volumes.size() - 1);
}

View File

@ -357,6 +357,8 @@ public:
// An ID containing the extruder ID (used to select color).
int extruder_id;
size_t model_object_ID{0};
// Various boolean flags.
struct {
// Is this object selected?
@ -634,7 +636,8 @@ public:
int instance_idx,
const std::string &color_by,
bool opengl_initialized,
bool in_assemble_view = false);
bool in_assemble_view = false,
bool use_loaded_id = false);
// Load SLA auxiliary GLVolumes (for support trees or pad).
void load_object_auxiliary(

View File

@ -1971,12 +1971,13 @@ void GLCanvas3D::render(bool only_init)
m_render_stats.increment_fps_counter();
}
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type)
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type, bool use_top_view, bool for_picking)
{
render_thumbnail(thumbnail_data, w, h, thumbnail_params, m_volumes, camera_type);
render_thumbnail(thumbnail_data, w, h, thumbnail_params, m_volumes, camera_type, use_top_view, for_picking);
}
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type)
void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
const GLVolumeCollection& volumes, Camera::EType camera_type, bool use_top_view, bool for_picking)
{
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
ModelObjectPtrs& model_objects = GUI::wxGetApp().model().objects;
@ -1985,10 +1986,10 @@ void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w,
{
case OpenGLManager::EFramebufferType::Arb:
{ render_thumbnail_framebuffer(thumbnail_data, w, h, thumbnail_params,
wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type); break; }
wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type, use_top_view, for_picking); break; }
case OpenGLManager::EFramebufferType::Ext:
{ render_thumbnail_framebuffer_ext(thumbnail_data, w, h, thumbnail_params,
wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type); break; }
wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type, use_top_view, for_picking); break; }
default:
{ render_thumbnail_legacy(thumbnail_data, w, h, thumbnail_params,
wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type); break; }
@ -5375,7 +5376,9 @@ static void debug_output_thumbnail(const ThumbnailData& thumbnail_data)
}
#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type)
void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params,
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view, bool for_picking)
{
//BBS modify visible calc function
int plate_idx = thumbnail_params.plate_id;
@ -5418,7 +5421,7 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
}
}
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: plate_idx %1% volumes size %2%, shader %3%") % plate_idx % visible_volumes.size() %shader;
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: plate_idx %1% volumes size %2%, shader %3%, use_top_view=%4%, for_picking=%5%") % plate_idx % visible_volumes.size() %shader %use_top_view %for_picking;
//BoundingBoxf3 volumes_box = plate_build_volume;
BoundingBoxf3 volumes_box;
volumes_box.min.z() = 0;
@ -5448,11 +5451,29 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
//BoundingBoxf3 plate_box = plate->get_bounding_box(false);
//plate_box.min.z() = 0.0;
//plate_box.max.z() = 0.0;
camera.zoom_to_box(volumes_box);
const Vec3d& target = camera.get_target();
double distance = camera.get_distance();
//camera.select_view("topfront");
camera.look_at(target - 0.707 * distance * Vec3d::UnitY() + 0.3 * distance * Vec3d::UnitZ(), target, Vec3d::UnitY() + Vec3d::UnitZ());
if (use_top_view) {
float center_x = (plate_build_volume.max(0) + plate_build_volume.min(0))/2;
float center_y = (plate_build_volume.max(1) + plate_build_volume.min(1))/2;
float distance_z = plate_build_volume.max(2) - plate_build_volume.min(2);
Vec3d center(center_x, center_y, 0.f);
double zoom_ratio, scale_x, scale_y;
scale_x = ((double)thumbnail_data.width)/(plate_build_volume.max(0) - plate_build_volume.min(0));
scale_y = ((double)thumbnail_data.height)/(plate_build_volume.max(1) - plate_build_volume.min(1));
zoom_ratio = (scale_x <= scale_y)?scale_x:scale_y;
camera.look_at(center + distance_z * Vec3d::UnitZ(), center, Vec3d::UnitY());
camera.set_zoom(zoom_ratio);
//camera.select_view("top");
}
else {
camera.zoom_to_box(volumes_box);
const Vec3d& target = camera.get_target();
double distance = camera.get_distance();
camera.look_at(target - 0.707 * distance * Vec3d::UnitY() + 0.3 * distance * Vec3d::UnitZ(), target, Vec3d::UnitY() + Vec3d::UnitZ());
}
camera.apply_view_matrix();
camera.apply_projection(plate_build_volume);
@ -5462,44 +5483,94 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
//camera.apply_projection(volumes_box, near_z, far_z);
//GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (shader == nullptr) {
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: shader is null, return directly");
if (!for_picking && (shader == nullptr)) {
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail with no picking: shader is null, return directly");
return;
}
//if (thumbnail_params.transparent_background)
glsafe(::glClearColor(0.906f, 0.906f, 0.906f, 1.0f));
if (for_picking)
glsafe(::glClearColor(0.f, 0.f, 0.f, 0.f));
else
glsafe(::glClearColor(0.906f, 0.906f, 0.906f, 1.0f));
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST));
shader->start_using();
shader->set_uniform("emission_factor", 0.0f);
if (for_picking) {
//if (OpenGLManager::can_multisample())
// This flag is often ignored by NVIDIA drivers if rendering into a screen buffer.
// glsafe(::glDisable(GL_MULTISAMPLE));
for (GLVolume* vol : visible_volumes) {
//BBS set render color for thumbnails
curr_color[0] = vol->color[0];
curr_color[1] = vol->color[1];
curr_color[2] = vol->color[2];
curr_color[3] = vol->color[3];
glsafe(::glDisable(GL_BLEND));
shader->set_uniform("uniform_color", curr_color);
//BBS set all volume to orange
//shader->set_uniform("uniform_color", orange);
/*if (plate_idx > 0) {
shader->set_uniform("uniform_color", orange);
static const GLfloat INV_255 = 1.0f / 255.0f;
// do not cull backfaces to show broken geometry, if any
glsafe(::glDisable(GL_CULL_FACE));
//glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
//glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
for (GLVolume* vol : visible_volumes) {
// Object picking mode. Render the object with a color encoding the object index.
// we reserve color = (0,0,0) for occluders (as the printbed)
// so we shift volumes' id by 1 to get the proper color
//BBS: remove the bed picking logic
unsigned int id = vol->model_object_ID;
//unsigned int id = 1 + volume.second.first;
unsigned int r = (id & (0x000000FF << 0)) >> 0;
unsigned int g = (id & (0x000000FF << 8)) >> 8;
unsigned int b = (id & (0x000000FF << 16)) >> 16;
unsigned int a = 0xFF;
glsafe(::glColor4f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255));
/*curr_color[0] = (GLfloat)r * INV_255;
curr_color[1] = (GLfloat)g * INV_255;
curr_color[2] = (GLfloat)b * INV_255;
curr_color[3] = (GLfloat)a * INV_255;
shader->set_uniform("uniform_color", curr_color);*/
bool is_active = vol->is_active;
vol->is_active = true;
vol->simple_render(nullptr, model_objects, extruder_colors);
vol->is_active = is_active;
}
else {
shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? orange : gray);
}*/
// the volume may have been deactivated by an active gizmo
bool is_active = vol->is_active;
vol->is_active = true;
vol->simple_render(shader, model_objects, extruder_colors);
vol->is_active = is_active;
}
shader->stop_using();
//glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
//glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnable(GL_CULL_FACE));
//if (OpenGLManager::can_multisample())
// glsafe(::glEnable(GL_MULTISAMPLE));
}
else {
shader->start_using();
shader->set_uniform("emission_factor", 0.0f);
for (GLVolume* vol : visible_volumes) {
//BBS set render color for thumbnails
curr_color[0] = vol->color[0];
curr_color[1] = vol->color[1];
curr_color[2] = vol->color[2];
curr_color[3] = vol->color[3];
shader->set_uniform("uniform_color", curr_color);
//BBS set all volume to orange
//shader->set_uniform("uniform_color", orange);
/*if (plate_idx > 0) {
shader->set_uniform("uniform_color", orange);
}
else {
shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? orange : gray);
}*/
// the volume may have been deactivated by an active gizmo
bool is_active = vol->is_active;
vol->is_active = true;
vol->simple_render(shader, model_objects, extruder_colors);
vol->is_active = is_active;
}
shader->stop_using();
}
glsafe(::glDisable(GL_DEPTH_TEST));
@ -5512,7 +5583,9 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: finished");
}
void GLCanvas3D::render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type)
void GLCanvas3D::render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view, bool for_picking)
{
thumbnail_data.set(w, h);
if (!thumbnail_data.is_valid())
@ -5563,7 +5636,7 @@ void GLCanvas3D::render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, uns
glsafe(::glDrawBuffers(1, drawBufs));
if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type);
render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type, use_top_view, for_picking);
if (multisample) {
GLuint resolve_fbo;
@ -5616,7 +5689,9 @@ void GLCanvas3D::render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, uns
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail prepare: finished");
}
void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type)
void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view, bool for_picking)
{
thumbnail_data.set(w, h);
if (!thumbnail_data.is_valid())
@ -5666,7 +5741,7 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data,
glsafe(::glDrawBuffers(1, drawBufs));
if (::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT) {
render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type);
render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type, use_top_view, for_picking);
if (multisample) {
GLuint resolve_fbo;
@ -7339,7 +7414,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
if (item->selected) {
ImGui::PushStyleColor(ImGuiCol_Button, button_active);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_active);
}
}
else {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(128.0f, 128.0f, 128.0f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.42f, 0.42f, 0.42f, 1.0f));
@ -7615,7 +7690,7 @@ void GLCanvas3D::_render_paint_toolbar() const
Slic3r::GUI::BitmapCache::parse_color(colors[i], rgb);
float gray = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2];
ImVec4 text_color = gray < 80 ? ImVec4(255, 255, 255, 255) : ImVec4(0, 0, 0, 255);
ImVec2 number_label_size = ImGui::CalcTextSize(std::to_string(i + 1).c_str());
ImGui::SetCursorPosY(cursor_y + text_offset_y);
ImGui::SetCursorPosX(item_spacing + i * (item_spacing + button_size) + (button_size - number_label_size.x) / 2);

View File

@ -832,13 +832,21 @@ public:
// printable_only == false -> render also non printable volumes as grayed
// parts_only == false -> render also sla support and pad
void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type);
void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, const GLVolumeCollection& volumes, Camera::EType camera_type);
static void render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type);
void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
void render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
const GLVolumeCollection& volumes, Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
static void render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects,
const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
// render thumbnail using an off-screen framebuffer
static void render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type);
static void render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
// render thumbnail using an off-screen framebuffer when GLEW_EXT_framebuffer_object is supported
static void render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type);
static void render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector<std::array<float, 4>>& extruder_colors,
GLShaderProgram* shader, Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
//BBS use gcoder viewer render calibration thumbnails
void render_calibration_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params);

View File

@ -2348,7 +2348,7 @@ int PartPlate::load_gcode_from_file(const std::string& filename)
return ret;
}
int PartPlate::load_thumbnail_data(std::string filename)
int PartPlate::load_thumbnail_data(std::string filename, ThumbnailData& thumb_data)
{
bool result = true;
wxImage img;
@ -2357,11 +2357,11 @@ int PartPlate::load_thumbnail_data(std::string filename)
img = img.Mirror(false);
}
if (result) {
thumbnail_data.set(img.GetWidth(), img.GetHeight());
thumb_data.set(img.GetWidth(), img.GetHeight());
for (int i = 0; i < img.GetWidth() * img.GetHeight(); i++) {
memcpy(&thumbnail_data.pixels[4 * i], (unsigned char*)(img.GetData() + 3 * i), 3);
memcpy(&thumb_data.pixels[4 * i], (unsigned char*)(img.GetData() + 3 * i), 3);
if (img.HasAlpha()) {
thumbnail_data.pixels[4 * i + 3] = *(unsigned char*)(img.GetAlpha() + i);
thumb_data.pixels[4 * i + 3] = *(unsigned char*)(img.GetAlpha() + i);
}
}
} else {
@ -2372,7 +2372,7 @@ int PartPlate::load_thumbnail_data(std::string filename)
int PartPlate::load_pattern_thumbnail_data(std::string filename)
{
bool result = true;
/*bool result = true;
wxImage img;
result = load_image(filename, img);
if (result) {
@ -2386,7 +2386,7 @@ int PartPlate::load_pattern_thumbnail_data(std::string filename)
}
else {
return -1;
}
}*/
return 0;
}
@ -3428,6 +3428,8 @@ int PartPlateList::notify_instance_update(int obj_id, int instance_id)
PartPlate* plate = m_plate_list[obj_id - 1000];
plate->update_slice_result_valid_state( false );
plate->thumbnail_data.reset();
plate->top_thumbnail_data.reset();
plate->pick_thumbnail_data.reset();
return 0;
}
@ -3456,10 +3458,14 @@ int PartPlateList::notify_instance_update(int obj_id, int instance_id)
plate->update_states();
plate->update_slice_result_valid_state();
plate->thumbnail_data.reset();
plate->top_thumbnail_data.reset();
plate->pick_thumbnail_data.reset();
return 0;
}
plate->update_slice_result_valid_state();
plate->thumbnail_data.reset();
plate->top_thumbnail_data.reset();
plate->pick_thumbnail_data.reset();
}
else if (unprintable_plate.contain_instance(obj_id, instance_id))
{
@ -3490,6 +3496,8 @@ int PartPlateList::notify_instance_update(int obj_id, int instance_id)
plate->add_instance(obj_id, instance_id, false, &boundingbox);
plate->update_slice_result_valid_state();
plate->thumbnail_data.reset();
plate->top_thumbnail_data.reset();
plate->pick_thumbnail_data.reset();
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": add it to new plate %1%") % i;
return 0;
}
@ -3525,6 +3533,8 @@ int PartPlateList::notify_instance_removed(int obj_id, int instance_id)
plate->remove_instance(obj_id, instance_to_delete);
plate->update_slice_result_valid_state();
plate->thumbnail_data.reset();
plate->top_thumbnail_data.reset();
plate->pick_thumbnail_data.reset();
}
if (unprintable_plate.contain_instance(obj_id, instance_to_delete))
@ -4416,6 +4426,11 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w
%(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]->top_thumbnail_data.is_valid())
plate_data_item->top_file = "valid_top";
if (m_plate_list[i]->pick_thumbnail_data.is_valid())
plate_data_item->pick_file = "valid_pick";
if (m_plate_list[i]->obj_to_instance_set.size() > 0)
{
for (std::set<std::pair<int, int>>::iterator it = m_plate_list[i]->obj_to_instance_set.begin(); it != m_plate_list[i]->obj_to_instance_set.end(); ++it)
@ -4430,8 +4445,8 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w
// 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_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;
@ -4513,17 +4528,29 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list)
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);
m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->thumbnail_file, m_plate_list[index]->thumbnail_data);
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();
}
}
if (m_plater && !plate_data_list[i]->pattern_file.empty()) {
/*if (m_plater && !plate_data_list[i]->pattern_file.empty()) {
if (boost::filesystem::exists(plate_data_list[i]->pattern_file)) {
//no need to load pattern data currently
//m_plate_list[index]->load_pattern_thumbnail_data(plate_data_list[i]->pattern_file);
}
}*/
if (m_plater && !plate_data_list[i]->top_file.empty()) {
if (boost::filesystem::exists(plate_data_list[i]->top_file)) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load top_thumbnail from %2%.")%(i+1) %plate_data_list[i]->top_file;
m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->top_file, m_plate_list[index]->top_thumbnail_data);
}
}
if (m_plater && !plate_data_list[i]->pick_file.empty()) {
if (boost::filesystem::exists(plate_data_list[i]->pick_file)) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load pick_thumbnail from %2%.")%(i+1) %plate_data_list[i]->pick_file;
m_plate_list[index]->load_thumbnail_data(plate_data_list[i]->pick_file, m_plate_list[index]->pick_thumbnail_data);
}
}
if (m_plater && !plate_data_list[i]->pattern_bbox_file.empty()) {
if (boost::filesystem::exists(plate_data_list[i]->pattern_bbox_file)) {

View File

@ -231,10 +231,13 @@ public:
static const int plate_thumbnail_width = 512;
static const int plate_thumbnail_height = 512;
ThumbnailData cali_thumbnail_data;
ThumbnailData top_thumbnail_data;
ThumbnailData pick_thumbnail_data;
//ThumbnailData cali_thumbnail_data;
PlateBBoxData cali_bboxes_data;
static const int cali_thumbnail_width = 2560;
static const int cali_thumbnail_height = 2560;
//static const int cali_thumbnail_width = 2560;
//static const int cali_thumbnail_height = 2560;
//set the plate's index
void set_index(int index);
@ -410,7 +413,7 @@ public:
//load gcode from file
int load_gcode_from_file(const std::string& filename);
//load thumbnail data from file
int load_thumbnail_data(std::string filename);
int load_thumbnail_data(std::string filename, ThumbnailData& thumb_data);
//load pattern thumbnail data from file
int load_pattern_thumbnail_data(std::string filename);
//load pattern box data from file

View File

@ -2109,7 +2109,8 @@ struct Plater::priv
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
//BBS: add plate_id for thumbnail
void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type);
void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
Camera::EType camera_type, bool use_top_view = false, bool for_picking = false);
ThumbnailsList generate_thumbnails(const ThumbnailsParams& params, Camera::EType camera_type);
//BBS
void generate_calibration_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params);
@ -6440,9 +6441,10 @@ void Plater::priv::on_3dcanvas_mouse_dragging_finished(SimpleEvent&)
}
//BBS: add plate id for thumbnail generate param
void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type)
void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params,
Camera::EType camera_type, bool use_top_view, bool for_picking)
{
view3D->get_canvas3d()->render_thumbnail(data, w, h, thumbnail_params, camera_type);
view3D->get_canvas3d()->render_thumbnail(data, w, h, thumbnail_params, camera_type, use_top_view, for_picking);
}
//BBS: add plate id for thumbnail generate param
@ -9523,6 +9525,7 @@ void Plater::export_stl(bool extended, bool selection_only)
// BBS: backup
int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy strategy, int export_plate_idx, Export3mfProgressFn proFn)
{
int ret = 0;
//if (p->model.objects.empty()) {
// MessageDialog dialog(nullptr, _L("No objects to export."), _L("Save project"), wxYES);
// if (dialog.ShowModal() == wxYES)
@ -9548,6 +9551,8 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
//BBS: add plate logic for thumbnail generate
std::vector<ThumbnailData*> thumbnails;
std::vector<ThumbnailData*> calibration_thumbnails;
std::vector<ThumbnailData*> top_thumbnails;
std::vector<ThumbnailData*> picking_thumbnails;
std::vector<PlateBBoxData*> plate_bboxes;
// BBS: backup
if (!(strategy & SaveStrategy::Backup)) {
@ -9560,22 +9565,50 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
else {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": re-generate thumbnail for plate %1%") % i;
const ThumbnailsParams thumbnail_params = { {}, false, true, true, true, i };
p->generate_thumbnail(p->partplate_list.get_plate(i)->thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, thumbnail_params, Camera::EType::Ortho);
p->generate_thumbnail(p->partplate_list.get_plate(i)->thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second,
thumbnail_params, Camera::EType::Ortho);
}
thumbnails.push_back(thumbnail_data);
ThumbnailData* calibration_data = &p->partplate_list.get_plate(i)->cali_thumbnail_data;
calibration_thumbnails.push_back(calibration_data);
//ThumbnailData* calibration_data = &p->partplate_list.get_plate(i)->cali_thumbnail_data;
//calibration_thumbnails.push_back(calibration_data);
PlateBBoxData* plate_bbox_data = &p->partplate_list.get_plate(i)->cali_bboxes_data;
plate_bboxes.push_back(plate_bbox_data);
//generate top and picking thumbnails
ThumbnailData* top_thumbnail = &p->partplate_list.get_plate(i)->top_thumbnail_data;
if (top_thumbnail->is_valid() && using_exported_file()) {
//no need to generate thumbnail
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": non need to re-generate top_thumbnail for gcode/exported mode of plate %1%")%i;
}
else {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": re-generate top_thumbnail for plate %1%") % i;
const ThumbnailsParams thumbnail_params = { {}, false, true, false, true, i };
p->generate_thumbnail(p->partplate_list.get_plate(i)->top_thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second,
thumbnail_params, Camera::EType::Ortho, true, false);
}
top_thumbnails.push_back(top_thumbnail);
ThumbnailData* picking_thumbnail = &p->partplate_list.get_plate(i)->pick_thumbnail_data;
if (picking_thumbnail->is_valid() && using_exported_file()) {
//no need to generate thumbnail
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": non need to re-generate pick_thumbnail for gcode/exported mode of plate %1%")%i;
}
else {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": re-generate pick_thumbnail for plate %1%") % i;
const ThumbnailsParams thumbnail_params = { {}, false, true, false, true, i };
p->generate_thumbnail(p->partplate_list.get_plate(i)->pick_thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second,
thumbnail_params, Camera::EType::Ortho, true, true);
}
picking_thumbnails.push_back(picking_thumbnail);
}
if (p->partplate_list.get_curr_plate()->is_slice_result_valid()) {
//BBS generate BBS calibration thumbnails
int index = p->partplate_list.get_curr_plate_index();
ThumbnailData* calibration_data = calibration_thumbnails[index];
const ThumbnailsParams calibration_params = { {}, false, true, true, true, p->partplate_list.get_curr_plate_index() };
p->generate_calibration_thumbnail(*calibration_data, PartPlate::cali_thumbnail_width, PartPlate::cali_thumbnail_height, calibration_params);
//ThumbnailData* calibration_data = calibration_thumbnails[index];
//const ThumbnailsParams calibration_params = { {}, false, true, true, true, p->partplate_list.get_curr_plate_index() };
//p->generate_calibration_thumbnail(*calibration_data, PartPlate::cali_thumbnail_width, PartPlate::cali_thumbnail_height, calibration_params);
if (using_exported_file()) {
//do nothing
}
@ -9600,6 +9633,8 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
store_params.project_presets = project_presets;
store_params.config = export_config ? &cfg : nullptr;
store_params.thumbnail_data = thumbnails;
store_params.top_thumbnail_data = top_thumbnails;
store_params.pick_thumbnail_data = picking_thumbnails;
store_params.calibration_thumbnail_data = calibration_thumbnails;
store_params.proFn = proFn;
store_params.id_bboxes = plate_bboxes;//BBS
@ -9661,7 +9696,7 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
}
}
else {
return -1;
ret = -1;
}
if (project_presets.size() > 0)
@ -9680,8 +9715,20 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
//release the data here, as it will always be generated when export
calibration_thumbnails[i]->reset();
}
for (unsigned int i = 0; i < top_thumbnails.size(); i++)
{
//release the data here, as it will always be generated when export
top_thumbnails[i]->reset();
}
top_thumbnails.clear();
for (unsigned int i = 0; i < picking_thumbnails.size(); i++)
{
//release the data here, as it will always be generated when export
picking_thumbnails[i]->reset();;
}
picking_thumbnails.clear();
return 0;
return ret;
}
void Plater::publish_project()