ENH: CLI: add logic for backward compatible check

1. add logic for backward compatible check
2. add export_stls

JIRA: no-jira
Change-Id: If96ab225b9689e588fae7443e81a73d0872f7eb4
(cherry picked from commit db12cca05c8f60fdc717387253215e361ab29851)
This commit is contained in:
lane.wei 2024-05-09 09:39:14 +08:00 committed by Lane.Wei
parent ebe5392932
commit 9b19dc9edd
5 changed files with 465 additions and 165 deletions

View File

@ -161,6 +161,8 @@ typedef struct _sliced_info {
std::vector<sliced_plate_info_t> sliced_plates; std::vector<sliced_plate_info_t> sliced_plates;
size_t prepare_time; size_t prepare_time;
size_t export_time; size_t export_time;
std::vector<std::string> upward_machines;
std::vector<std::string> downward_machines;
}sliced_info_t; }sliced_info_t;
std::vector<PrintBase::SlicingStatus> g_slicing_warnings; std::vector<PrintBase::SlicingStatus> g_slicing_warnings;
@ -409,6 +411,10 @@ void record_exit_reson(std::string outputdir, int code, int plate_id, std::strin
try { try {
json j; json j;
//record the headers //record the headers
if (sliced_info.downward_machines.size() > 0)
j["downward_compatible_machine"] = sliced_info.downward_machines;
if (sliced_info.upward_machines.size() > 0)
j["upward_compatible_machine"] = sliced_info.upward_machines;
j["plate_index"] = plate_id; j["plate_index"] = plate_id;
j["return_code"] = code; j["return_code"] = code;
j["error_string"] = error_message; j["error_string"] = error_message;
@ -979,8 +985,6 @@ int CLI::run(int argc, char **argv)
PrinterTechnology printer_technology = get_printer_technology(m_config); PrinterTechnology printer_technology = get_printer_technology(m_config);
bool start_gui = m_actions.empty();
//BBS: remove GCodeViewer as seperate APP logic //BBS: remove GCodeViewer as seperate APP logic
/*bool start_as_gcodeviewer = /*bool start_as_gcodeviewer =
#ifdef _WIN32 #ifdef _WIN32
@ -990,8 +994,8 @@ int CLI::run(int argc, char **argv)
boost::algorithm::iends_with(boost::filesystem::path(argv[0]).filename().string(), "gcodeviewer"); boost::algorithm::iends_with(boost::filesystem::path(argv[0]).filename().string(), "gcodeviewer");
#endif // _WIN32*/ #endif // _WIN32*/
bool translate_old = false, regenerate_thumbnails = false, shrink_to_new_bed = false, filament_color_changed = false; bool translate_old = false, regenerate_thumbnails = false, filament_color_changed = false;
int current_printable_width, current_printable_depth, current_printable_height; int current_printable_width, current_printable_depth, current_printable_height, shrink_to_new_bed = 0;
int old_printable_height = 0, old_printable_width = 0, old_printable_depth = 0; int old_printable_height = 0, old_printable_width = 0, old_printable_depth = 0;
Pointfs old_printable_area, old_exclude_area; Pointfs old_printable_area, old_exclude_area;
float old_max_radius = 0.f, old_height_to_rod = 0.f, old_height_to_lid = 0.f; float old_max_radius = 0.f, old_height_to_rod = 0.f, old_height_to_lid = 0.f;
@ -1000,6 +1004,8 @@ int CLI::run(int argc, char **argv)
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;
const std::vector<std::string> &uptodate_configs = m_config.option<ConfigOptionStrings>("uptodate_settings", true)->values; const std::vector<std::string> &uptodate_configs = m_config.option<ConfigOptionStrings>("uptodate_settings", true)->values;
const std::vector<std::string> &uptodate_filaments = m_config.option<ConfigOptionStrings>("uptodate_filaments", true)->values; const std::vector<std::string> &uptodate_filaments = m_config.option<ConfigOptionStrings>("uptodate_filaments", true)->values;
const std::vector<std::string> &downward_check = m_config.option<ConfigOptionStrings>("downward_check", true)->values;
std::vector<std::string> downward_compatible_machines;
//BBS: always use ForwardCompatibilitySubstitutionRule::Enable //BBS: always use ForwardCompatibilitySubstitutionRule::Enable
//const ForwardCompatibilitySubstitutionRule config_substitution_rule = m_config.option<ConfigOptionEnum<ForwardCompatibilitySubstitutionRule>>("config_compatibility", true)->value; //const ForwardCompatibilitySubstitutionRule config_substitution_rule = m_config.option<ConfigOptionEnum<ForwardCompatibilitySubstitutionRule>>("config_compatibility", true)->value;
const ForwardCompatibilitySubstitutionRule config_substitution_rule = ForwardCompatibilitySubstitutionRule::Enable; const ForwardCompatibilitySubstitutionRule config_substitution_rule = ForwardCompatibilitySubstitutionRule::Enable;
@ -1012,6 +1018,7 @@ int CLI::run(int argc, char **argv)
sliced_info_t sliced_info; sliced_info_t sliced_info;
std::map<std::string, std::string> record_key_values; std::map<std::string, std::string> record_key_values;
bool start_gui = m_actions.empty() && downward_check.empty();
if (start_gui) { if (start_gui) {
BOOST_LOG_TRIVIAL(info) << "no action, start gui directly" << std::endl; BOOST_LOG_TRIVIAL(info) << "no action, start gui directly" << std::endl;
::Label::initSysFont(); ::Label::initSysFont();
@ -1080,6 +1087,7 @@ int CLI::run(int argc, char **argv)
//BBS: add plate data related logic //BBS: add plate data related logic
PlateDataPtrs plate_data_src; PlateDataPtrs plate_data_src;
std::vector<plate_obj_size_info_t> plate_obj_size_infos;
int arrange_option; int arrange_option;
int plate_to_slice = 0, filament_count = 0, duplicate_count = 0, real_duplicate_count = 0; int plate_to_slice = 0, filament_count = 0, duplicate_count = 0, real_duplicate_count = 0;
bool first_file = true, is_bbl_3mf = false, need_arrange = true, has_thumbnails = false, up_config_to_date = false, normative_check = true, duplicate_single_object = false, use_first_fila_as_default = false, minimum_save = false, enable_timelapse = false; bool first_file = true, is_bbl_3mf = false, need_arrange = true, has_thumbnails = false, up_config_to_date = false, normative_check = true, duplicate_single_object = false, use_first_fila_as_default = false, minimum_save = false, enable_timelapse = false;
@ -2100,7 +2108,7 @@ int CLI::run(int argc, char **argv)
} }
//upwards check //upwards check
bool process_compatible = false, machine_upwards = false; bool process_compatible = false, machine_upwards = false, machine_switch = false;
BOOST_LOG_TRIVIAL(info) << boost::format("current printer %1%, new printer %2%, current process %3%, new process %4%")%current_printer_name %new_printer_name %current_process_name %new_process_name; BOOST_LOG_TRIVIAL(info) << boost::format("current printer %1%, new printer %2%, current process %3%, new process %4%")%current_printer_name %new_printer_name %current_process_name %new_process_name;
BOOST_LOG_TRIVIAL(info) << boost::format("current printer inherits %1%, new printer inherits %2%, current process inherits %3%, new process inherits %4%") BOOST_LOG_TRIVIAL(info) << boost::format("current printer inherits %1%, new printer inherits %2%, current process inherits %3%, new process inherits %4%")
%current_printer_system_name %new_printer_system_name %current_process_system_name %new_process_system_name; %current_printer_system_name %new_printer_system_name %current_process_system_name %new_process_system_name;
@ -2162,11 +2170,16 @@ int CLI::run(int argc, char **argv)
%current_printer_name %current_printer_system_name %current_process_name %current_process_system_name %process_compatible; %current_printer_name %current_printer_system_name %current_process_name %current_process_system_name %process_compatible;
} }
if (!process_compatible && !new_printer_name.empty() && !current_printer_name.empty() && (new_printer_name != current_printer_name)) { if (!process_compatible && !new_printer_name.empty() && !current_printer_name.empty() && (new_printer_name != current_printer_name)) {
//set all printer to compatible
process_compatible = true;
machine_switch = true;
BOOST_LOG_TRIVIAL(info) << boost::format("switch to new printers, set to compatible");
if (upward_compatible_printers.size() > 0) { if (upward_compatible_printers.size() > 0) {
for (int index = 0; index < upward_compatible_printers.size(); index++) { for (int index = 0; index < upward_compatible_printers.size(); index++) {
if (upward_compatible_printers[index] == new_printer_system_name) { if (upward_compatible_printers[index] == new_printer_system_name) {
process_compatible = true; process_compatible = true;
machine_upwards = true; machine_upwards = true;
BOOST_LOG_TRIVIAL(info) << boost::format("new printer is upward_compatible");
break; break;
} }
} }
@ -2176,11 +2189,11 @@ int CLI::run(int argc, char **argv)
flush_and_exit(CLI_3MF_NEW_MACHINE_NOT_SUPPORTED); flush_and_exit(CLI_3MF_NEW_MACHINE_NOT_SUPPORTED);
} }
} }
else { /*else {
BOOST_LOG_TRIVIAL(error) <<__FUNCTION__ << boost::format(" %1%: current 3mf file not support upward_compatible_printers, can not change machine preset.")%__LINE__; BOOST_LOG_TRIVIAL(error) <<__FUNCTION__ << boost::format(" %1%: current 3mf file not support upward_compatible_printers, can not change machine preset.")%__LINE__;
record_exit_reson(outfile_dir, CLI_3MF_NOT_SUPPORT_MACHINE_CHANGE, 0, cli_errors[CLI_3MF_NOT_SUPPORT_MACHINE_CHANGE], sliced_info); record_exit_reson(outfile_dir, CLI_3MF_NOT_SUPPORT_MACHINE_CHANGE, 0, cli_errors[CLI_3MF_NOT_SUPPORT_MACHINE_CHANGE], sliced_info);
flush_and_exit(CLI_3MF_NOT_SUPPORT_MACHINE_CHANGE); flush_and_exit(CLI_3MF_NOT_SUPPORT_MACHINE_CHANGE);
} }*/
} }
if (!process_compatible) { if (!process_compatible) {
@ -2188,10 +2201,11 @@ int CLI::run(int argc, char **argv)
record_exit_reson(outfile_dir, CLI_PROCESS_NOT_COMPATIBLE, 0, cli_errors[CLI_PROCESS_NOT_COMPATIBLE], sliced_info); record_exit_reson(outfile_dir, CLI_PROCESS_NOT_COMPATIBLE, 0, cli_errors[CLI_PROCESS_NOT_COMPATIBLE], sliced_info);
flush_and_exit(CLI_PROCESS_NOT_COMPATIBLE); flush_and_exit(CLI_PROCESS_NOT_COMPATIBLE);
} }
sliced_info.upward_machines = upward_compatible_printers;
//create project embedded preset if needed //create project embedded preset if needed
Preset *new_preset = NULL; Preset *new_preset = NULL;
if (is_bbl_3mf && machine_upwards) { if (is_bbl_3mf && machine_switch) {
//we need to update the compatible printer and create a new process here, or if we load the 3mf in studio, the process preset can not be loaded as not compatible //we need to update the compatible printer and create a new process here, or if we load the 3mf in studio, the process preset can not be loaded as not compatible
Preset *current_preset = NULL; Preset *current_preset = NULL;
size_t project_presets_count = project_presets.size(); size_t project_presets_count = project_presets.size();
@ -2467,7 +2481,7 @@ int CLI::run(int argc, char **argv)
} }
} }
if (machine_upwards) { if (machine_switch) {
print_compatible_printers.push_back(new_printer_system_name); print_compatible_printers.push_back(new_printer_system_name);
std::string old_setting = different_settings[0]; std::string old_setting = different_settings[0];
@ -2852,134 +2866,6 @@ int CLI::run(int argc, char **argv)
flush_and_exit(CLI_INVALID_VALUES_IN_3MF); flush_and_exit(CLI_INVALID_VALUES_IN_3MF);
} }
//BBS: partplate list
Slic3r::GUI::PartPlateList partplate_list(NULL, m_models.data(), printer_technology);
//use Pointfs insteadof Points
Pointfs current_printable_area = m_print_config.opt<ConfigOptionPoints>("printable_area")->values;
Pointfs current_exclude_area = m_print_config.opt<ConfigOptionPoints>("bed_exclude_area")->values;
//update part plate's size
double print_height = m_print_config.opt_float("printable_height");
double height_to_lid = m_print_config.opt_float("extruder_clearance_height_to_lid");
double height_to_rod = m_print_config.opt_float("extruder_clearance_height_to_rod");
double cleareance_radius = m_print_config.opt_float("extruder_clearance_max_radius");
//double plate_stride;
std::string bed_texture;
current_printable_width = current_printable_area[2].x() - current_printable_area[0].x();
current_printable_depth = current_printable_area[2].y() - current_printable_area[0].y();
current_printable_height = print_height;
if (old_printable_width == 0)
old_printable_width = current_printable_width;
if (old_printable_depth == 0)
old_printable_depth = current_printable_depth;
if (old_printable_height == 0)
old_printable_height = current_printable_height;
if ((old_printable_width > 0)&&(old_printable_depth > 0)&&(old_printable_height > 0))
{
//check the printable size logic
//if ((old_printable_width > current_printable_width) || (old_printable_depth > current_printable_depth) || (old_printable_height > current_printable_height))
if ((old_printable_width > current_printable_width) || (old_printable_depth > current_printable_depth))
{
BOOST_LOG_TRIVIAL(error) << boost::format("old printable size {%1%, %2%, %3%} is larger than new printable size {%4%, %5%, %6%}, can not print")
%old_printable_width %old_printable_depth %old_printable_height %current_printable_width %current_printable_depth %current_printable_height;
record_exit_reson(outfile_dir, CLI_PRINTABLE_SIZE_REDUCED, 0, cli_errors[CLI_PRINTABLE_SIZE_REDUCED], sliced_info);
flush_and_exit(CLI_PRINTABLE_SIZE_REDUCED);
}
else if ((old_printable_width < current_printable_width) || (old_printable_depth < current_printable_depth))
{
BOOST_LOG_TRIVIAL(info) << boost::format("old printable size {%1%, %2%, %3%} is smaller than new printable size {%4%, %5%, %6%}, need to center the model")
%old_printable_width %old_printable_depth %old_printable_height %current_printable_width %current_printable_depth %current_printable_height;
shrink_to_new_bed = true;
}
else {
BOOST_LOG_TRIVIAL(info) << boost::format("old printable size {%1%, %2%, %3%}, new printable size {%4%, %5%, %6%}")
%old_printable_width %old_printable_depth %old_printable_height %current_printable_width %current_printable_depth %current_printable_height;
}
}
if (m_models.size() > 0)
{
BOOST_LOG_TRIVIAL(info) << boost::format("translate_old %1%, shrink_to_new_bed %2%, old bed size {%3%, %4%, %5%}")%translate_old%shrink_to_new_bed %old_printable_width %old_printable_depth %old_printable_height;
if (translate_old) {
BOOST_LOG_TRIVIAL(info) << boost::format("translate old 3mf, switch to older bed size,{%1%, %2%, %3%}")%(old_printable_width + bed3d_ax3s_default_tip_radius)%(old_printable_depth+bed3d_ax3s_default_tip_radius) %old_printable_height;
partplate_list.reset_size(old_printable_width + bed3d_ax3s_default_tip_radius, old_printable_depth + bed3d_ax3s_default_tip_radius, old_printable_height, false);
}
else {
partplate_list.reset_size(old_printable_width, old_printable_depth, old_printable_height, false);
}
partplate_list.set_shapes(current_printable_area, current_exclude_area, bed_texture, height_to_lid, height_to_rod);
//plate_stride = partplate_list.plate_stride_x();
}
auto translate_models = [translate_old, shrink_to_new_bed, old_printable_width, old_printable_depth, old_printable_height, current_printable_width, current_printable_depth, current_printable_height] (Slic3r::GUI::PartPlateList& plate_list, DynamicPrintConfig& print_config) {
//BBS: translate old 3mf to correct positions
if (translate_old) {
//translate the objects
int plate_count = plate_list.get_plate_count();
for (int index = 1; index < plate_count; index ++) {
Slic3r::GUI::PartPlate* cur_plate = (Slic3r::GUI::PartPlate *)plate_list.get_plate(index);
Vec3d cur_origin = cur_plate->get_origin();
Vec3d new_origin = plate_list.compute_origin_using_new_size(index, old_printable_width, old_printable_depth);
cur_plate->translate_all_instance(new_origin - cur_origin);
}
BOOST_LOG_TRIVIAL(info) << boost::format("translate old 3mf, switch back to current bed size,{%1%, %2%, %3%}")%old_printable_width %old_printable_depth %old_printable_height;
plate_list.reset_size(old_printable_width, old_printable_depth, old_printable_height, true, true);
}
if (shrink_to_new_bed)
{
int plate_count = plate_list.get_plate_count();
ConfigOptionFloats *wipe_x_option = nullptr, *wipe_y_option = nullptr;
Vec3d wipe_offset;
if (print_config.has("wipe_tower_x")) {
wipe_x_option = dynamic_cast<ConfigOptionFloats *>(print_config.option("wipe_tower_x"));
wipe_y_option = dynamic_cast<ConfigOptionFloats *>(print_config.option("wipe_tower_y"));
}
for (int index = 0; index < plate_count; index ++) {
Slic3r::GUI::PartPlate* cur_plate = (Slic3r::GUI::PartPlate *)plate_list.get_plate(index);
Vec3d cur_origin = cur_plate->get_origin();
Vec3d new_origin = plate_list.compute_origin_using_new_size(index, current_printable_width, current_printable_depth);
Vec3d cur_center_offset { ((double)old_printable_width)/2, ((double)old_printable_depth)/2, 0}, new_center_offset { ((double)current_printable_width)/2, ((double)current_printable_depth)/2, 0};
Vec3d cur_center = cur_origin + cur_center_offset;
Vec3d new_center = new_origin + new_center_offset;
Vec3d offset = new_center - cur_center;
cur_plate->translate_all_instance(offset);
if (index == 0)
wipe_offset = offset;
if (wipe_x_option) {
BOOST_LOG_TRIVIAL(info) << boost::format("shrink_to_new_bed, plate %1%: wipe tower src: {%2%, %3%}")%(index+1) %wipe_x_option->get_at(index) %wipe_y_option->get_at(index);
ConfigOptionFloat wipe_tower_x(wipe_x_option->get_at(index) + wipe_offset(0));
ConfigOptionFloat wipe_tower_y(wipe_y_option->get_at(index) + wipe_offset(1));
wipe_x_option->set_at(&wipe_tower_x, index, 0);
wipe_y_option->set_at(&wipe_tower_y, index, 0);
BOOST_LOG_TRIVIAL(info) << boost::format("shrink_to_new_bed, plate %1% wipe tower changes to: {%2%, %3%}")%(index+1) %wipe_x_option->get_at(index) %wipe_y_option->get_at(index);
}
BOOST_LOG_TRIVIAL(info) << boost::format("shrink_to_new_bed, plate %1% translate offset: {%2%, %3%, %4%}")%(index+1) %offset[0] %offset[1] %offset[2];
}
BOOST_LOG_TRIVIAL(info) << boost::format("shrink_to_new_bed, shrink all the models to current bed size,{%1%, %2%, %3%}")%current_printable_width %current_printable_depth %current_printable_height;
plate_list.reset_size(current_printable_width, current_printable_depth, current_printable_height, true, true);
}
};
if (plate_data_src.size() > 0)
{
partplate_list.load_from_3mf_structure(plate_data_src);
translate_models(partplate_list, m_print_config);
}
/*for (ModelObject *model_object : m_models[0].objects)
for (ModelInstance *model_instance : model_object->instances)
{
const Vec3d &instance_offset = model_instance->get_offset();
BOOST_LOG_TRIVIAL(info) << boost::format("instance %1% transform {%2%,%3%,%4%} at %5%:%6%")% model_object->name % instance_offset.x() % instance_offset.y() %instance_offset.z() % __FUNCTION__ % __LINE__<< std::endl;
}*/
auto timelapse_type_opt = m_print_config.option("timelapse_type"); auto timelapse_type_opt = m_print_config.option("timelapse_type");
bool is_smooth_timelapse = false; bool is_smooth_timelapse = false;
if (enable_timelapse && timelapse_type_opt && (timelapse_type_opt->getInt() == TimelapseType::tlSmooth)) if (enable_timelapse && timelapse_type_opt && (timelapse_type_opt->getInt() == TimelapseType::tlSmooth))
@ -3015,6 +2901,366 @@ int CLI::run(int argc, char **argv)
} }
} }
//BBS: partplate list
Slic3r::GUI::PartPlateList partplate_list(NULL, m_models.data(), printer_technology);
//use Pointfs insteadof Points
Pointfs current_printable_area = m_print_config.opt<ConfigOptionPoints>("printable_area")->values;
Pointfs current_exclude_area = m_print_config.opt<ConfigOptionPoints>("bed_exclude_area")->values;
//update part plate's size
double print_height = m_print_config.opt_float("printable_height");
double height_to_lid = m_print_config.opt_float("extruder_clearance_height_to_lid");
double height_to_rod = m_print_config.opt_float("extruder_clearance_height_to_rod");
double cleareance_radius = m_print_config.opt_float("extruder_clearance_max_radius");
//double plate_stride;
std::string bed_texture;
current_printable_width = current_printable_area[2].x() - current_printable_area[0].x();
current_printable_depth = current_printable_area[2].y() - current_printable_area[0].y();
current_printable_height = print_height;
if (old_printable_width == 0)
old_printable_width = current_printable_width;
if (old_printable_depth == 0)
old_printable_depth = current_printable_depth;
if (old_printable_height == 0)
old_printable_height = current_printable_height;
if ((old_printable_width > 0)&&(old_printable_depth > 0)&&(old_printable_height > 0))
{
//check the printable size logic
//if ((old_printable_width > current_printable_width) || (old_printable_depth > current_printable_depth) || (old_printable_height > current_printable_height))
if ((old_printable_width > current_printable_width) || (old_printable_depth > current_printable_depth) || (old_printable_height > current_printable_height))
{
BOOST_LOG_TRIVIAL(error) << boost::format("old printable size {%1%, %2%, %3%} is larger than new printable size {%4%, %5%, %6%}, the object size should be limited")
%old_printable_width %old_printable_depth %old_printable_height %current_printable_width %current_printable_depth %current_printable_height;
/*record_exit_reson(outfile_dir, CLI_PRINTABLE_SIZE_REDUCED, 0, cli_errors[CLI_PRINTABLE_SIZE_REDUCED], sliced_info);
flush_and_exit(CLI_PRINTABLE_SIZE_REDUCED);*/
shrink_to_new_bed = 2;
}
else if ((old_printable_width < current_printable_width) || (old_printable_depth < current_printable_depth))
{
BOOST_LOG_TRIVIAL(info) << boost::format("old printable size {%1%, %2%, %3%} is smaller than new printable size {%4%, %5%, %6%}, need to center the model")
%old_printable_width %old_printable_depth %old_printable_height %current_printable_width %current_printable_depth %current_printable_height;
shrink_to_new_bed = 1;
}
else {
if ((current_exclude_area.size() > 0)&&(current_exclude_area != old_exclude_area)) {
BOOST_LOG_TRIVIAL(info) << boost::format("old printable size {%1%, %2%, %3%}, new printable size {%4%, %5%, %6%}, exclude_area different, need to shrink")
%old_printable_width %old_printable_depth %old_printable_height %current_printable_width %current_printable_depth %current_printable_height;
shrink_to_new_bed = 2;
}
else {
BOOST_LOG_TRIVIAL(info) << boost::format("old printable size {%1%, %2%, %3%}, new printable size {%4%, %5%, %6%}, extract the same, no need shrink")
%old_printable_width %old_printable_depth %old_printable_height %current_printable_width %current_printable_depth %current_printable_height;
}
}
}
if (m_models.size() > 0)
{
BOOST_LOG_TRIVIAL(info) << boost::format("translate_old %1%, shrink_to_new_bed %2%, old bed size {%3%, %4%, %5%}")%translate_old%shrink_to_new_bed %old_printable_width %old_printable_depth %old_printable_height;
if (translate_old) {
BOOST_LOG_TRIVIAL(info) << boost::format("translate old 3mf, switch to older bed size,{%1%, %2%, %3%}")%(old_printable_width + bed3d_ax3s_default_tip_radius)%(old_printable_depth+bed3d_ax3s_default_tip_radius) %old_printable_height;
partplate_list.reset_size(old_printable_width + bed3d_ax3s_default_tip_radius, old_printable_depth + bed3d_ax3s_default_tip_radius, old_printable_height, false);
}
else {
partplate_list.reset_size(old_printable_width, old_printable_depth, old_printable_height, false);
}
partplate_list.set_shapes(current_printable_area, current_exclude_area, bed_texture, height_to_lid, height_to_rod);
//plate_stride = partplate_list.plate_stride_x();
}
auto get_print_sequence = [](Slic3r::GUI::PartPlate* plate, DynamicPrintConfig& print_config, bool &is_seq_print) {
PrintSequence curr_plate_seq = plate->get_print_seq();
if (curr_plate_seq == PrintSequence::ByDefault) {
auto seq_print = print_config.option<ConfigOptionEnum<PrintSequence>>("print_sequence");
if (seq_print && (seq_print->value == PrintSequence::ByObject)) {
BOOST_LOG_TRIVIAL(info) << boost::format("plate print by object, set from global");
is_seq_print = true;
}
}
else if (curr_plate_seq == PrintSequence::ByObject) {
BOOST_LOG_TRIVIAL(info) << boost::format("plate print by object, set from plate self");
is_seq_print = true;
}
};
auto check_plate_wipe_tower = [get_print_sequence, is_smooth_timelapse](Slic3r::GUI::PartPlate* plate, int plate_index, DynamicPrintConfig& print_config, plate_obj_size_info_t &plate_obj_size_info) {
plate_obj_size_info.obj_bbox= plate->get_objects_bounding_box();
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, object bbox: min {%2%, %3%, %4%} - max {%5%, %6%, %7%}")
%(plate_index+1) %plate_obj_size_info.obj_bbox.min.x() % plate_obj_size_info.obj_bbox.min.y() % plate_obj_size_info.obj_bbox.min.z() %plate_obj_size_info.obj_bbox.max.x() % plate_obj_size_info.obj_bbox.max.y() % plate_obj_size_info.obj_bbox.max.z();
if (!print_config.has("wipe_tower_x")) {
plate_obj_size_info.has_wipe_tower = false;
BOOST_LOG_TRIVIAL(info) << boost::format("can not found wipe_tower_x in config, set to no wipe tower");
return;
}
int valid_count = plate->printable_instance_size();
if (valid_count <= 0){
plate_obj_size_info.has_wipe_tower = false;
BOOST_LOG_TRIVIAL(info) << boost::format("no printable object found, set to no wipe tower");
return;
}
bool is_sequence = false;
get_print_sequence(plate, print_config, is_sequence);
if (is_sequence && valid_count > 1) {
plate_obj_size_info.has_wipe_tower = false;
BOOST_LOG_TRIVIAL(info) << boost::format("sequence print, valid_count=%1%, set to no wipe tower")%valid_count;
return;
}
std::vector<int> extruders = plate->get_extruders_under_cli(true, print_config);
unsigned int filaments_cnt = extruders.size();
if ((filaments_cnt <= 1) && !is_smooth_timelapse){
plate_obj_size_info.has_wipe_tower = false;
BOOST_LOG_TRIVIAL(info) << boost::format("filaments_cnt=%1%, set to no wipe tower")%filaments_cnt;
return;
}
ConfigOptionFloats *wipe_x_option = dynamic_cast<ConfigOptionFloats *>(print_config.option("wipe_tower_x"));
ConfigOptionFloats *wipe_y_option = dynamic_cast<ConfigOptionFloats *>(print_config.option("wipe_tower_y"));
plate_obj_size_info.wipe_x = wipe_x_option->get_at(plate_index);
plate_obj_size_info.wipe_y = wipe_y_option->get_at(plate_index);
ConfigOptionFloat* width_option = print_config.option<ConfigOptionFloat>("prime_tower_width", true);
plate_obj_size_info.wipe_width = width_option->value;
ConfigOptionFloat* brim_width_option = print_config.option<ConfigOptionFloat>("prime_tower_brim_width", true);
float brim_width = brim_width_option->value;
ConfigOptionFloat* volume_option = print_config.option<ConfigOptionFloat>("prime_volume", true);
float wipe_volume = volume_option->value;
Vec3d wipe_tower_size = plate->estimate_wipe_tower_size(print_config, plate_obj_size_info.wipe_width, wipe_volume, filaments_cnt);
plate_obj_size_info.wipe_depth = wipe_tower_size(1);
Vec3d origin = plate->get_origin();
Vec3d start(origin(0) + plate_obj_size_info.wipe_x - brim_width, origin(1) + plate_obj_size_info.wipe_y, 0.f);
plate_obj_size_info.obj_bbox.merge(start);
Vec3d end(origin(0) + plate_obj_size_info.wipe_x + plate_obj_size_info.wipe_width + brim_width, origin(1) + plate_obj_size_info.wipe_y + plate_obj_size_info.wipe_depth, 0.f);
plate_obj_size_info.obj_bbox.merge(end);
plate_obj_size_info.has_wipe_tower = true;
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, has wipe tower, wipe bbox: min {%2%, %3%, %4%} - max {%5%, %6%, %7%}")
%(plate_index+1) %start.x() % start.y() % start.z() %end.x() % end.y() % end.z();
};
auto translate_models = [translate_old, shrink_to_new_bed, old_printable_width, old_printable_depth, old_printable_height, current_printable_width, current_printable_depth, current_printable_height, current_exclude_area, &plate_obj_size_infos] (Slic3r::GUI::PartPlateList& plate_list, DynamicPrintConfig& print_config) {
//BBS: translate old 3mf to correct positions
if (translate_old) {
//translate the objects
int plate_count = plate_list.get_plate_count();
for (int index = 1; index < plate_count; index ++) {
Slic3r::GUI::PartPlate* cur_plate = (Slic3r::GUI::PartPlate *)plate_list.get_plate(index);
Vec3d cur_origin = cur_plate->get_origin();
Vec3d new_origin = plate_list.compute_origin_using_new_size(index, old_printable_width, old_printable_depth);
cur_plate->translate_all_instance(new_origin - cur_origin);
}
BOOST_LOG_TRIVIAL(info) << boost::format("translate old 3mf, switch back to current bed size,{%1%, %2%, %3%}")%old_printable_width %old_printable_depth %old_printable_height;
plate_list.reset_size(old_printable_width, old_printable_depth, old_printable_height, true, true);
}
if (shrink_to_new_bed > 0)
{
int plate_count = plate_list.get_plate_count();
ConfigOptionFloats *wipe_x_option = nullptr, *wipe_y_option = nullptr;
Vec3d wipe_offset;
if (print_config.has("wipe_tower_x")) {
wipe_x_option = dynamic_cast<ConfigOptionFloats *>(print_config.option("wipe_tower_x"));
wipe_y_option = dynamic_cast<ConfigOptionFloats *>(print_config.option("wipe_tower_y"));
}
double exclude_width = 0.f, exclude_depth = 0.f;
if (current_exclude_area.size() >= 4) {
exclude_width = current_exclude_area[2].x() - current_exclude_area[0].x();
exclude_depth = current_exclude_area[2].y() - current_exclude_area[0].y();
}
for (int index = 0; index < plate_count; index ++) {
Slic3r::GUI::PartPlate* cur_plate = (Slic3r::GUI::PartPlate *)plate_list.get_plate(index);
Vec3d cur_origin = cur_plate->get_origin();
Vec3d new_origin = plate_list.compute_origin_using_new_size(index, current_printable_width, current_printable_depth);
Vec3d offset;
if (shrink_to_new_bed == 1) {
Vec3d cur_center_offset { ((double)old_printable_width)/2, ((double)old_printable_depth)/2, 0}, new_center_offset { ((double)current_printable_width)/2, ((double)current_printable_depth)/2, 0};
Vec3d cur_center = cur_origin + cur_center_offset;
Vec3d new_center = new_origin + new_center_offset;
offset = new_center - cur_center;
if (index == 0)
wipe_offset = offset;
BOOST_LOG_TRIVIAL(info) << boost::format("shrink_to_new_bed 1, plate %1%, cur_origin: {%2%, %3%}, new_origin: {%4%, %5%}, cur_center {%6%, %7%} new_center {%8%, %9%}")
%(index+1) %cur_origin(0) %cur_origin(1) %new_origin(0) %new_origin(1) %cur_center(0) %cur_center(1) %new_center(0) %new_center(1);
}
else {
//center the object
Vec3d new_center_offset { ((double)current_printable_width + exclude_width)/2, ((double)current_printable_depth + exclude_depth)/2, 0};
BoundingBoxf3& bbox = plate_obj_size_infos[index].obj_bbox;
Vec3d size = bbox.size();
if (size.x() > (current_printable_width - exclude_width))
new_center_offset(0) = ((double)current_printable_width)/2;
if (size.y() > (current_printable_depth - exclude_depth))
new_center_offset(1) = ((double)current_printable_depth)/2;
Vec3d new_center = new_origin + new_center_offset;
offset = new_center - bbox.center();
wipe_offset = offset + cur_origin - new_origin;
BOOST_LOG_TRIVIAL(info) << boost::format("shrink_to_new_bed 2, plate %1%, new_origin: {%2%, %3%}, new_center: {%4%, %5%}, obj bbox(including wipe tower) min {%6%, %7%} max {%8%, %9%}")
%(index+1) %new_origin(0) %new_origin(1) %new_center(0) %new_center(1) %bbox.min(0) %bbox.min(1) %bbox.max(0) %bbox.max(1);
}
offset(2) = 0.f;
BOOST_LOG_TRIVIAL(info) << boost::format("shrink_to_new_bed %1%, plate %2% translate offset: {%3%, %4%} wipe_offset {%5%, %6%}") %shrink_to_new_bed %(index+1) %offset[0] %offset[1] %wipe_offset[0] %wipe_offset[1];
cur_plate->translate_all_instance(offset);
if (wipe_x_option) {
BOOST_LOG_TRIVIAL(info) << boost::format("shrink_to_new_bed %4%, plate %1%: wipe tower src: {%2%, %3%}")%(index+1) %wipe_x_option->get_at(index) %wipe_y_option->get_at(index)%shrink_to_new_bed;
ConfigOptionFloat wipe_tower_x(wipe_x_option->get_at(index) + wipe_offset(0));
ConfigOptionFloat wipe_tower_y(wipe_y_option->get_at(index) + wipe_offset(1));
wipe_x_option->set_at(&wipe_tower_x, index, 0);
wipe_y_option->set_at(&wipe_tower_y, index, 0);
BOOST_LOG_TRIVIAL(info) << boost::format("shrink_to_new_bed %4%, plate %1% wipe tower changes to: {%2%, %3%}")%(index+1) %wipe_x_option->get_at(index) %wipe_y_option->get_at(index) %shrink_to_new_bed;
}
}
BOOST_LOG_TRIVIAL(info) << boost::format("shrink_to_new_bed, shrink all the models to current bed size,{%1%, %2%, %3%}")%current_printable_width %current_printable_depth %current_printable_height;
plate_list.reset_size(current_printable_width, current_printable_depth, current_printable_height, true, true);
}
};
if (plate_data_src.size() > 0)
{
partplate_list.load_from_3mf_structure(plate_data_src);
int plate_count = partplate_list.get_plate_count();
plate_obj_size_infos.resize(plate_count, plate_obj_size_info_t());
for (int index = 0; index < plate_count; index ++) {
Slic3r::GUI::PartPlate* cur_plate = (Slic3r::GUI::PartPlate *)partplate_list.get_plate(index);
check_plate_wipe_tower(cur_plate, index, m_print_config, plate_obj_size_infos[index]);
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, has_wipe_tower %2%, wipe_x %3%, wipe_y %4%, width %5%, depth %6%")
%(index+1) %plate_obj_size_infos[index].has_wipe_tower %plate_obj_size_infos[index].wipe_x %plate_obj_size_infos[index].wipe_y %plate_obj_size_infos[index].wipe_width %plate_obj_size_infos[index].wipe_depth;
}
translate_models(partplate_list, m_print_config);
}
/*for (ModelObject *model_object : m_models[0].objects)
for (ModelInstance *model_instance : model_object->instances)
{
const Vec3d &instance_offset = model_instance->get_offset();
BOOST_LOG_TRIVIAL(info) << boost::format("instance %1% transform {%2%,%3%,%4%} at %5%:%6%")% model_object->name % instance_offset.x() % instance_offset.y() %instance_offset.z() % __FUNCTION__ % __LINE__<< std::endl;
}*/
//doing downward_check
std::vector<printer_plate_info_t> downward_check_printers;
std::vector<bool> downward_check_status;
for (auto const &file : downward_check) {
DynamicPrintConfig config;
std::string config_type, config_name, filament_id, config_from, downward_printer;
int ret = load_config_file(file, config, config_type, config_name, filament_id, config_from);
if (ret) {
record_exit_reson(outfile_dir, ret, 0, cli_errors[ret], sliced_info);
flush_and_exit(ret);
}
if ((config_type != "machine") || (config_from != "system")) {
BOOST_LOG_TRIVIAL(info) << boost::format("found invalid config type %1% or from %2% in file %3% when downward_check")%config_type %config_from %file;
record_exit_reson(outfile_dir, ret, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info);
flush_and_exit(ret);
}
BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: loaded machine config %1%, from %2%")%config_name %file ;
printer_plate_info_t printer_plate;
Pointfs temp_printable_area, temp_exclude_area;
printer_plate.printer_name = config_name;
temp_printable_area = config.option<ConfigOptionPoints>("printable_area", true)->values;
temp_exclude_area = config.option<ConfigOptionPoints>("bed_exclude_area", true)->values;
if (temp_printable_area.size() >= 4) {
printer_plate.printable_width = (int)(temp_printable_area[2].x() - temp_printable_area[0].x());
printer_plate.printable_depth = (int)(temp_printable_area[2].y() - temp_printable_area[0].y());
printer_plate.printable_height = (int)(config.opt_float("printable_height"));
}
if (temp_exclude_area.size() >= 4) {
printer_plate.exclude_width = (int)(temp_exclude_area[2].x() - temp_exclude_area[0].x());
printer_plate.exclude_depth = (int)(temp_exclude_area[2].y() - temp_exclude_area[0].y());
printer_plate.exclude_x = (int)temp_exclude_area[0].x();
printer_plate.exclude_y = (int)temp_exclude_area[0].y();
}
BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: printable size{%1%,%2%, %3%}, exclude area{%4%, %5%: %6% x %7%}")
%printer_plate.printable_width %printer_plate.printable_depth %printer_plate.printable_height
%printer_plate.exclude_x %printer_plate.exclude_y %printer_plate.exclude_width %printer_plate.exclude_depth;
downward_check_printers.push_back(std::move(printer_plate));
}
int downward_check_size = downward_check_printers.size();
if (downward_check_size > 0)
{
downward_check_status.resize(downward_check_size, false);
int plate_count = partplate_list.get_plate_count();
int failed_count = 0;
for (int index = 0; index < plate_count; index ++)
{
if (failed_count == downward_check_size) {
BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: all failed, size %1%")%downward_check_size;
break;
}
Slic3r::GUI::PartPlate* cur_plate = (Slic3r::GUI::PartPlate *)partplate_list.get_plate(index);
Vec3d size = plate_obj_size_infos[index].obj_bbox.size();
for (int index2 = 0; index2 < downward_check_size; index2 ++)
{
if (failed_count == downward_check_size) {
break;
}
if (downward_check_status[index2])
continue;
printer_plate_info_t& plate_info = downward_check_printers[index2];
if ((size.z() > plate_info.printable_height) || (size.y() > plate_info.printable_depth) || (size.x() > plate_info.printable_width)) {
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, downward_check index %2%, name %3%, bbox {%4%, %5%, %6%} exceeds printer size {%7%, %8%, %9%}")
%(index+1) %(index2+1) %plate_info.printer_name
%size.x() % size.y() % size.z() %plate_info.printable_width %plate_info.printable_depth %plate_info.printable_height;
downward_check_status[index2] = true;
failed_count ++;
continue;
}
if (plate_info.exclude_width > 0) {
int real_width = plate_info.printable_width - plate_info.exclude_width;
int real_depth = plate_info.printable_depth - plate_info.exclude_depth;
if ((size.x() > real_width) && (size.y() > real_depth)) {
BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%, downward_check index %2%, name %3%, bbox {%4%, %5%} exceeds real size without exclude_area {%6%, %7%}")
%(index+1) %(index2+1) %plate_info.printer_name
%size.x() % size.y() %real_width %real_depth;
downward_check_status[index2] = true;
failed_count ++;
continue;
}
}
}
}
if (failed_count < downward_check_size)
{
//has success ones
BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: downward_check_size %1%, failed_count %2%")%downward_check_size %failed_count;
for (int index2 = 0; index2 < downward_check_size; index2 ++)
{
if (downward_check_status[index2])
continue;
printer_plate_info_t& plate_info = downward_check_printers[index2];
BOOST_LOG_TRIVIAL(info) << boost::format("downward_check: found compatible printer %1%")%plate_info.printer_name;
downward_compatible_machines.push_back(plate_info.printer_name);
}
sliced_info.downward_machines = downward_compatible_machines;
}
}
// Loop through transform options. // Loop through transform options.
bool user_center_specified = false; bool user_center_specified = false;
Points beds = get_bed_shape(m_print_config); Points beds = get_bed_shape(m_print_config);
@ -3410,21 +3656,6 @@ int CLI::run(int argc, char **argv)
} }
} }
auto get_print_sequence = [](Slic3r::GUI::PartPlate* plate, DynamicPrintConfig& print_config, bool &is_seq_print) {
PrintSequence curr_plate_seq = plate->get_print_seq();
if (curr_plate_seq == PrintSequence::ByDefault) {
auto seq_print = print_config.option<ConfigOptionEnum<PrintSequence>>("print_sequence");
if (seq_print && (seq_print->value == PrintSequence::ByObject)) {
BOOST_LOG_TRIVIAL(info) << boost::format("plate print by object, set from global");
is_seq_print = true;
}
}
else if (curr_plate_seq == PrintSequence::ByObject) {
BOOST_LOG_TRIVIAL(info) << boost::format("plate print by object, set from plate self");
is_seq_print = true;
}
};
if (!assemble_plate_info_list.empty()) if (!assemble_plate_info_list.empty())
{ {
//need to arrange for assemble cases //need to arrange for assemble cases
@ -4241,7 +4472,7 @@ int CLI::run(int argc, char **argv)
// loop through action options // loop through action options
bool export_to_3mf = false, load_slicedata = false, export_slicedata = false, export_slicedata_error = false; bool export_to_3mf = false, load_slicedata = false, export_slicedata = false, export_slicedata_error = false;
bool no_check = false; bool no_check = false;
std::string export_3mf_file, load_slice_data_dir, export_slice_data_dir; std::string export_3mf_file, load_slice_data_dir, export_slice_data_dir, export_stls_dir;
std::vector<ThumbnailData*> calibration_thumbnails; std::vector<ThumbnailData*> calibration_thumbnails;
std::vector<int> plate_object_count(partplate_list.get_plate_count(), 0); std::vector<int> plate_object_count(partplate_list.get_plate_count(), 0);
int max_slicing_time_per_plate = 0, max_triangle_count_per_plate = 0, sliced_plate = -1; int max_slicing_time_per_plate = 0, max_triangle_count_per_plate = 0, sliced_plate = -1;
@ -4275,9 +4506,9 @@ int CLI::run(int argc, char **argv)
record_exit_reson(outfile_dir, CLI_INVALID_PARAMS, 0, cli_errors[CLI_INVALID_PARAMS], sliced_info); record_exit_reson(outfile_dir, CLI_INVALID_PARAMS, 0, cli_errors[CLI_INVALID_PARAMS], sliced_info);
flush_and_exit(CLI_INVALID_PARAMS); flush_and_exit(CLI_INVALID_PARAMS);
} }
else if (shrink_to_new_bed) else if (shrink_to_new_bed > 0)
{ {
BOOST_LOG_TRIVIAL(warning) << "use load_slicedata when shrink_to_new_bed(switch printer from small to bigger." << std::endl; BOOST_LOG_TRIVIAL(warning) << "use load_slicedata when shrink_to_new_bed." << std::endl;
//record_exit_reson(outfile_dir, CLI_INVALID_PARAMS, 0, cli_errors[CLI_INVALID_PARAMS], sliced_info); //record_exit_reson(outfile_dir, CLI_INVALID_PARAMS, 0, cli_errors[CLI_INVALID_PARAMS], sliced_info);
//flush_and_exit(CLI_INVALID_PARAMS); //flush_and_exit(CLI_INVALID_PARAMS);
} }
@ -4309,6 +4540,14 @@ int CLI::run(int argc, char **argv)
record_exit_reson(outfile_dir, CLI_EXPORT_STL_ERROR, 0, cli_errors[CLI_EXPORT_STL_ERROR], sliced_info); record_exit_reson(outfile_dir, CLI_EXPORT_STL_ERROR, 0, cli_errors[CLI_EXPORT_STL_ERROR], sliced_info);
flush_and_exit(CLI_EXPORT_STL_ERROR); flush_and_exit(CLI_EXPORT_STL_ERROR);
} }
} else if (opt_key == "export_stls") {
export_stls_dir = m_config.opt_string(opt_key);
for (auto &model : m_models)
model.add_default_instances();
if (! this->export_models(IO::STL, export_stls_dir)) {
record_exit_reson(outfile_dir, CLI_EXPORT_STL_ERROR, 0, cli_errors[CLI_EXPORT_STL_ERROR], sliced_info);
flush_and_exit(CLI_EXPORT_STL_ERROR);
}
} else if (opt_key == "export_obj") { } else if (opt_key == "export_obj") {
for (auto &model : m_models) for (auto &model : m_models)
model.add_default_instances(); model.add_default_instances();
@ -5666,7 +5905,7 @@ void CLI::print_help(bool include_print_options, PrinterTechnology printer_techn
}*/ }*/
} }
bool CLI::export_models(IO::ExportFormat format) bool CLI::export_models(IO::ExportFormat format, std::string path_dir)
{ {
for (Model &model : m_models) { for (Model &model : m_models) {
const std::string path = this->output_filepath(model, format); const std::string path = this->output_filepath(model, format);
@ -5687,7 +5926,7 @@ bool CLI::export_models(IO::ExportFormat format)
unsigned int index = 1; unsigned int index = 1;
for (ModelObject* model_object : model.objects) for (ModelObject* model_object : model.objects)
{ {
const std::string path = this->output_filepath(*model_object, index++, format); const std::string path = this->output_filepath(*model_object, index++, format, path_dir);
success = Slic3r::store_stl(path.c_str(), model_object, true); success = Slic3r::store_stl(path.c_str(), model_object, true);
if (success) if (success)
BOOST_LOG_TRIVIAL(info) << "Model successfully exported to " << path << std::endl; BOOST_LOG_TRIVIAL(info) << "Model successfully exported to " << path << std::endl;
@ -5770,7 +6009,7 @@ std::string CLI::output_filepath(const Model &model, IO::ExportFormat format) co
return proposed_path.string(); return proposed_path.string();
} }
std::string CLI::output_filepath(const ModelObject &object, unsigned int index, IO::ExportFormat format) const std::string CLI::output_filepath(const ModelObject &object, unsigned int index, IO::ExportFormat format, std::string path_dir) const
{ {
std::string ext, subdir, file_name, output_path; std::string ext, subdir, file_name, output_path;
switch (format) { switch (format) {
@ -5799,10 +6038,15 @@ std::string CLI::output_filepath(const ModelObject &object, unsigned int index,
if (pos != ext_pos) if (pos != ext_pos)
file_name += ext; file_name += ext;
BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << ": file_name="<<file_name<< ", pos = "<<pos<<", ext_pos="<<ext_pos; BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << ": dir = "<< path_dir<<", file_name="<<file_name<< ", pos = "<<pos<<", ext_pos="<<ext_pos;
std::string cmdline_param = m_config.opt_string("outputdir"); if (path_dir.empty()) {
if (! cmdline_param.empty()) { std::string cmdline_param = m_config.opt_string("outputdir");
subdir = cmdline_param + "/" + subdir; if (! cmdline_param.empty()) {
subdir = cmdline_param + "/" + subdir;
}
}
else {
subdir = path_dir;
} }
output_path = subdir + "/"+file_name; output_path = subdir + "/"+file_name;

View File

@ -67,6 +67,28 @@ typedef struct _assemble_plate_info {
}assemble_plate_info_t; }assemble_plate_info_t;
typedef struct _printer_plate_info {
std::string printer_name;
int printable_width{0};
int printable_depth{0};
int printable_height{0};
int exclude_width{0};
int exclude_depth{0};
int exclude_x{0};
int exclude_y{0};
}printer_plate_info_t;
typedef struct _plate_obj_size_info {
bool has_wipe_tower{false};
float wipe_x{0.f};
float wipe_y{0.f};
float wipe_width{0.f};
float wipe_depth{0.f};
BoundingBoxf3 obj_bbox;
}plate_obj_size_info_t;
class CLI { class CLI {
public: public:
int run(int argc, char **argv); int run(int argc, char **argv);
@ -86,7 +108,7 @@ private:
void print_help(bool include_print_options = false, PrinterTechnology printer_technology = ptAny) const; void print_help(bool include_print_options = false, PrinterTechnology printer_technology = ptAny) const;
/// Exports loaded models to a file of the specified format, according to the options affecting output filename. /// Exports loaded models to a file of the specified format, according to the options affecting output filename.
bool export_models(IO::ExportFormat format); bool export_models(IO::ExportFormat format, std::string path = std::string());
//BBS: add export_project function //BBS: add export_project function
bool export_project(Model *model, std::string& path, PlateDataPtrs &partplate_data, std::vector<Preset*>& project_presets, bool export_project(Model *model, std::string& path, PlateDataPtrs &partplate_data, std::vector<Preset*>& project_presets,
std::vector<ThumbnailData *> &thumbnails, std::vector<ThumbnailData *> &thumbnails,
@ -99,7 +121,7 @@ private:
bool has_print_action() const { return m_config.opt_bool("export_gcode") || m_config.opt_bool("export_sla"); } bool has_print_action() const { return m_config.opt_bool("export_gcode") || m_config.opt_bool("export_sla"); }
std::string output_filepath(const Model &model, IO::ExportFormat format) const; std::string output_filepath(const Model &model, IO::ExportFormat format) const;
std::string output_filepath(const ModelObject &object, unsigned int index, IO::ExportFormat format) const; std::string output_filepath(const ModelObject &object, unsigned int index, IO::ExportFormat format, std::string path_dir) const;
}; };
} }

View File

@ -5406,9 +5406,14 @@ CLIActionsConfigDef::CLIActionsConfigDef()
def = this->add("export_stl", coBool); def = this->add("export_stl", coBool);
def->label = "Export STL"; def->label = "Export STL";
def->tooltip = "Export the objects as multiple STL."; def->tooltip = "Export the objects as single STL.";
def->set_default_value(new ConfigOptionBool(false)); def->set_default_value(new ConfigOptionBool(false));
def = this->add("export_stls", coString);
def->label = "Export multiple stls";
def->tooltip = "Export the objects as multiple stls to directory";
def->set_default_value(new ConfigOptionString("stl_path"));
/*def = this->add("export_gcode", coBool); /*def = this->add("export_gcode", coBool);
def->label = L("Export G-code"); def->label = L("Export G-code");
def->tooltip = L("Slice the model and export toolpaths as G-code."); def->tooltip = L("Slice the model and export toolpaths as G-code.");
@ -5688,6 +5693,12 @@ CLIMiscConfigDef::CLIMiscConfigDef()
def->cli_params = "\"filament1.json;filament2.json;...\""; def->cli_params = "\"filament1.json;filament2.json;...\"";
def->set_default_value(new ConfigOptionStrings()); def->set_default_value(new ConfigOptionStrings());
def = this->add("downward_check", coStrings);
def->label = "downward machines check";
def->tooltip = "check whether current machine downward compatible with the machines in the list";
def->cli_params = "\"machine1.json;machine2.json;...\"";
def->set_default_value(new ConfigOptionStrings());
def = this->add("load_assemble_list", coString); def = this->add("load_assemble_list", coString);
def->label = "Load assemble list"; def->label = "Load assemble list";
def->tooltip = "Load assemble object list from config file"; def->tooltip = "Load assemble object list from config file";

View File

@ -2216,6 +2216,28 @@ int PartPlate::remove_instance(int obj_id, int instance_id)
return result; return result;
} }
BoundingBoxf3 PartPlate::get_objects_bounding_box()
{
BoundingBoxf3 bbox;
for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
{
int obj_id = it->first;
int instance_id = it->second;
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
{
ModelObject* object = m_model->objects[obj_id];
if ((instance_id >= 0) && (instance_id < object->instances.size()))
{
BoundingBoxf3 instance_bbox = object->instance_bounding_box(instance_id);
bbox.merge(instance_bbox);
}
}
}
return bbox;
}
//translate instance on the plate //translate instance on the plate
void PartPlate::translate_all_instance(Vec3d position) void PartPlate::translate_all_instance(Vec3d position)
{ {

View File

@ -304,6 +304,7 @@ public:
ModelObjectPtrs get_objects() { return m_model->objects; } ModelObjectPtrs get_objects() { return m_model->objects; }
ModelObjectPtrs get_objects_on_this_plate(); ModelObjectPtrs get_objects_on_this_plate();
ModelInstance* get_instance(int obj_id, int instance_id); ModelInstance* get_instance(int obj_id, int instance_id);
BoundingBoxf3 get_objects_bounding_box();
Vec3d get_origin() { return m_origin; } Vec3d get_origin() { return m_origin; }
Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int plate_extruder_size = 0, bool use_global_objects = false) const; Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int plate_extruder_size = 0, bool use_global_objects = false) const;