ENH: CLI: support multi-extruder slicing

1. add slicing errors for gcode in unprintable area, also for filament mapping
2. use common area for auto arrange
3. support filament_map/filament_map_mode related params
4. add logic to check the filament maps before slicing
5. uptodate support multi-extruder
6. switch new machine/filament support multi-extruder
7. process config params support transfer between mult-extruder and
   single-extruder
8. improve machine-limit logic support multi-extruder
9. flush-volume support multi-extruder
10. add default params to support auto mapping slicing

jira: no-jira
Change-Id: Ice39a365841322ddb586d39c56ff923626822528
This commit is contained in:
lane.wei 2024-10-23 16:07:59 +08:00
parent 8fca76aac9
commit f518d6804a
5 changed files with 536 additions and 67 deletions

View File

@ -144,8 +144,10 @@ std::map<int, std::string> cli_errors = {
{CLI_OBJECT_COLLISION_IN_SEQ_PRINT, "Object conflicts were detected when using print-by-object mode. Please verify the slicing of all plates in Bambu Studio before uploading."},
{CLI_OBJECT_COLLISION_IN_LAYER_PRINT, "Object conflicts were detected. Please verify the slicing of all plates in Bambu Studio before uploading."},
{CLI_SPIRAL_MODE_INVALID_PARAMS, "Some slicing parameters cannot work with Spiral Vase mode. Please solve the issue in Bambu Studio before uploading."},
{CLI_FILAMENT_CAN_NOT_MAP, "Some filaments cannot be mapped to correct extruders for multi-extruder Printer."},
{CLI_SLICING_ERROR, "Failed slicing the model. Please verify the slicing of all plates on Bambu Studio before uploading."},
{CLI_GCODE_PATH_CONFLICTS, " G-code conflicts detected after slicing. Please make sure the 3mf file can be successfully sliced in the latest Bambu Studio."},
{CLI_GCODE_PATH_IN_UNPRINTABLE_AREA, "Found G-code in unprintable area of multi-extruder printers after slicing. Please make sure the 3mf file can be successfully sliced in the latest Bambu Studio."}
{CLI_FILAMENT_UNPRINTABLE_ON_FIRST_LAYER, "Found some filament unprintable at first layer on current Plate. Please make sure the 3mf file can be successfully sliced with the same Plate type in the latest Bambu Studio."}
};
@ -1254,22 +1256,22 @@ static void load_downward_settings_list_from_config(std::string config_file, std
json downward_check_json = printer_model_json["downward_check"];
if (downward_check_json.contains(printer_name)) {
downward_settings = downward_check_json[printer_name].get<std::vector<std::string>>();
BOOST_LOG_TRIVIAL(info) << boost::format("got %1% downward settings of %2% in cli_config.json")%downward_settings.size() %printer_name;
BOOST_LOG_TRIVIAL(info) << boost::format("got %1% downward settings of %2% in %3%")%downward_settings.size() %printer_name %config_file;
}
else {
BOOST_LOG_TRIVIAL(info) << boost::format("can not find %1% in downward_check of %2% in cli_config.json")%printer_name %printer_model;
BOOST_LOG_TRIVIAL(info) << boost::format("can not find %1% in downward_check of %2% in %3%")%printer_name %printer_model %config_file;
}
}
else {
BOOST_LOG_TRIVIAL(info) << boost::format("can not find downward_check for %1% in cli_config.json")%printer_model;
BOOST_LOG_TRIVIAL(info) << boost::format("can not find downward_check for %1% in %2%")%printer_model%config_file;
}
}
else {
BOOST_LOG_TRIVIAL(info) << boost::format("can not find printer_model %1% in the file")%printer_model;
BOOST_LOG_TRIVIAL(info) << boost::format("can not find printer_model %1% in %2%")%printer_model%config_file;
}
}
else {
BOOST_LOG_TRIVIAL(warning) << boost::format("can not find key printer in the file");
BOOST_LOG_TRIVIAL(warning) << boost::format("can not find key printer in %1%")%config_file;
}
}
catch (std::exception &err) {
@ -1317,27 +1319,24 @@ 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 = 16;
char* debug_argv[] = {
"F:\work\projects\bambu_debug\bamboo_slicer\build_debug\src\Debug\bambu-studio.exe",
"--debug=2",
//"--uptodate",
//"--load-settings",
//"machine_A1.json",
//"--load-defaultfila",
//"--load-filaments",
//"filament_pla_basic_A1.json;filament_pla_basic_A1.json",
"--uptodate",
"--load-settings",
"machine.json",
"--load-filaments",
"filament_pla_matte.json;filament_pla_basic.json;filament_pla_matte.json;filament_pla_matte.json",
"--export-3mf=output.3mf",
//"--filament-colour",
//"#CD056D;#702829",
//"--nozzle-volume-type",
//"Standard,High Flow",
//"--filament-map-mode",
//"Auto",
//"--filament-map",
//"1,2,1,2",
"--slice=0",
"stl_test.3mf"
"--nozzle-volume-type",
"Normal,Big Traffic",
"--filament-map-mode",
"Auto",
"--filament-map",
"1,2,1,2",
"--slice=1",
"cube_o1d.3mf"
};
if (! this->setup(debug_argc, debug_argv))*/
if (!this->setup(argc, argv))
@ -1463,15 +1462,15 @@ int CLI::run(int argc, char **argv)
PlateDataPtrs plate_data_src;
std::vector<plate_obj_size_info_t> plate_obj_size_infos;
//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, current_extruder_count = 0, new_extruder_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 allow_rotations = true, skip_modified_gcodes = false, avoid_extrusion_cali_region = false, skip_useless_pick = false, allow_newer_file = false;
bool allow_rotations = true, skip_modified_gcodes = false, avoid_extrusion_cali_region = false, skip_useless_pick = false, allow_newer_file = false, current_is_multi_extruder = false, new_is_multi_extruder = false;
Semver file_version;
std::map<size_t, bool> orients_requirement;
std::vector<Preset*> project_presets;
std::string new_printer_name, current_printer_name, new_process_name, current_process_name, current_printer_system_name, current_process_system_name, new_process_system_name, new_printer_system_name, printer_model_id, current_printer_model, printer_model;//, printer_inherits, print_inherits;
std::string new_printer_name, current_printer_name, new_process_name, current_process_name, current_printer_system_name, current_process_system_name, new_process_system_name, new_printer_system_name, printer_model_id, current_printer_model, printer_model, new_default_process_name;
std::vector<std::string> upward_compatible_printers, new_print_compatible_printers, current_print_compatible_printers, current_different_settings;
std::vector<std::string> current_filaments_name, current_filaments_system_name, current_inherits_group;
std::vector<std::string> current_filaments_name, current_filaments_system_name, current_inherits_group, current_extruder_variants;
DynamicPrintConfig load_process_config, load_machine_config;
bool new_process_config_is_system = true, new_printer_config_is_system = true;
std::string pipe_name, makerlab_name, makerlab_version, different_process_setting;
@ -1716,6 +1715,19 @@ int CLI::run(int argc, char **argv)
current_process_name = config.option<ConfigOptionString>("print_settings_id")->value;
current_printer_model = config.option<ConfigOptionString>("printer_model", true)->value;
current_filaments_name = config.option<ConfigOptionStrings>("filament_settings_id")->values;
current_extruder_count = config.option<ConfigOptionFloatsNullable>("nozzle_diameter")->values.size();
current_is_multi_extruder = current_extruder_count > 1;
if (current_is_multi_extruder) {
auto opt_extruder_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(config.option("extruder_type"));
auto opt_nozzle_volume_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(config.option("nozzle_volume_type"));
current_extruder_variants.resize(current_extruder_count, "");
for (int e_index = 0; e_index < current_extruder_count; e_index++)
{
ExtruderType extruder_type = (ExtruderType)(opt_extruder_type->get_at(e_index));
NozzleVolumeType nozzle_volume_type = (NozzleVolumeType)(opt_nozzle_volume_type->get_at(e_index));
current_extruder_variants[e_index] = get_extruder_variant_string(extruder_type, nozzle_volume_type);
}
}
BOOST_LOG_TRIVIAL(info) << boost::format("current_printer_name %1%, current_process_name %2%")%current_printer_name %current_process_name;
ConfigOptionStrings* option_strings = config.option<ConfigOptionStrings>("inherits_group");
@ -2053,6 +2065,9 @@ int CLI::run(int argc, char **argv)
}
}
}
//new_default_process_name
if (config.option<ConfigOptionString>("default_print_profile"))
new_default_process_name = config.option<ConfigOptionString>("default_print_profile")->value;
//printer_inherits = config.option<ConfigOptionString>("inherits", true)->value;
load_machine_config = std::move(config);
@ -2610,6 +2625,7 @@ int CLI::run(int argc, char **argv)
}
if (!process_compatible && !new_printer_name.empty() && !current_printer_name.empty() && (new_printer_name != current_printer_name)) {
//set all printer to compatible
if (new_process_name.empty())
process_compatible = true;
machine_switch = true;
BOOST_LOG_TRIVIAL(info) << boost::format("switch to new printers, set to compatible");
@ -2860,6 +2876,8 @@ int CLI::run(int argc, char **argv)
flush_and_exit(ret);
}
}
new_extruder_count = m_print_config.option<ConfigOptionFloatsNullable>("nozzle_diameter")->values.size();
new_is_multi_extruder = new_extruder_count > 1;
//set the process settings into print config
std::vector<std::string>& print_compatible_printers = m_print_config.option<ConfigOptionStrings>("print_compatible_printers", true)->values;
@ -2901,7 +2919,7 @@ int CLI::run(int argc, char **argv)
int ret;
load_default_gcodes_to_config(load_machine_config, Preset::TYPE_PRINT);
load_default_gcodes_to_config(load_process_config, Preset::TYPE_PRINT);
if (new_process_name.empty()) {
int diff_keys_size = different_keys_set.size();
ret = update_full_config(m_print_config, load_process_config, different_keys_set, false, skip_modified_gcodes);
@ -2946,11 +2964,70 @@ int CLI::run(int argc, char **argv)
if (need_insert)
different_settings[0] = old_setting + ";compatible_printers";
}
//add multi-extruder related logic
if (new_process_name.empty() && (current_is_multi_extruder != new_is_multi_extruder)) {
if (new_default_process_name.empty()) {
BOOST_LOG_TRIVIAL(error) << boost::format("machine_switch: default process configis null, should not happen, new_printer_name %1%")%new_printer_name;
record_exit_reson(outfile_dir, CLI_CONFIG_FILE_ERROR, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info);
flush_and_exit(CLI_CONFIG_FILE_ERROR);
}
else {
std::string default_path = resources_dir() + "/profiles/BBL/process_full/";
std::string file_path = default_path + new_default_process_name + ".json";
DynamicPrintConfig config;
std::string config_type, config_name, filament_id, config_from, downward_printer;
int ret = load_config_file(file_path, 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 != "process") || (config_from != "system")) {
BOOST_LOG_TRIVIAL(error) << boost::format("found invalid config type %1% or from %2% in file %3% when downward_check")%config_type %config_from %file_path;
record_exit_reson(outfile_dir, CLI_CONFIG_FILE_ERROR, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info);
flush_and_exit(CLI_CONFIG_FILE_ERROR);
}
BOOST_LOG_TRIVIAL(info) << boost::format("machine_switch: loaded default process config %1%, from %2%")%config_name %file_path ;
if (!current_is_multi_extruder && new_is_multi_extruder) {
//single -> multiple
ret = m_print_config.update_values_from_single_to_multi(config, print_options_with_variant, "print_extruder_id", "print_extruder_variant");
}
else if (current_is_multi_extruder && !new_is_multi_extruder) {
//multiple -> single
ret = m_print_config.update_values_from_multi_to_single(config, print_options_with_variant, "print_extruder_id", "print_extruder_variant", current_extruder_variants);
}
if (ret) {
BOOST_LOG_TRIVIAL(error) << boost::format("current_is_multi_extruder %1% new_is_multi_extruder %2%, update_values failed") % current_is_multi_extruder % new_is_multi_extruder;
record_exit_reson(outfile_dir, CLI_CONFIG_FILE_ERROR, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info);
flush_and_exit(CLI_CONFIG_FILE_ERROR);
}
}
}
}
//set the filament settings into print config
if ((load_filament_count > 0) || (up_config_to_date))
{
std::vector<int> filament_variant_count(filament_count, 1);
std::vector<int> old_start_index(filament_count, 0);
std::vector<int> old_variant_count(filament_count, 1);
if (current_is_multi_extruder) {
std::vector<int>& old_self_indice = m_print_config.option<ConfigOptionInts>("filament_self_index", true)->values;
int old_self_indice_size = old_self_indice.size();
int k = -1, current_filament = 0;
for (size_t i = 0; i < old_self_indice_size; i++) {
if (old_self_indice[i] > current_filament) {
current_filament = old_self_indice[i];
old_start_index[++k] = i;
old_variant_count[k] = 1;
}
else {
old_variant_count[k] = old_variant_count[k] + 1;
}
}
}
for (int index = 0; index < load_filaments_config.size(); index++) {
DynamicPrintConfig& config = load_filaments_config[index];
int filament_index = load_filaments_index[index];
@ -3056,6 +3133,24 @@ 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 (new_is_multi_extruder && (filament_options_with_variant.find(opt_key) != filament_options_with_variant.end())) {
if (load_filament_count > 0) {
if (filament_index == 1)
opt_vec_dst->set(opt_vec_src);
else
opt_vec_dst->append(opt_vec_src);
if (opt_key == "filament_extruder_variant")
filament_variant_count[filament_index - 1] = opt_vec_src->size();
}
else {
//only update
for (size_t i = 0; i < old_variant_count[filament_index-1]; i++) {
opt_vec_dst->set_at(opt_vec_src, old_start_index[filament_index - 1] + i, i);
}
}
}
else
opt_vec_dst->set_at(opt_vec_src, filament_index-1, 0);
}
}
@ -3070,6 +3165,18 @@ int CLI::run(int argc, char **argv)
BOOST_LOG_TRIVIAL(info) << boost::format("filament %1% new different key size %2%, different_settings %3%")%filament_index %different_keys_set.size() %different_settings[filament_index];
}
}
if ((load_filament_count > 0) && m_print_config.option<ConfigOptionStrings>("filament_extruder_variant")) {
std::vector<int>& filament_self_indice = m_print_config.option<ConfigOptionInts>("filament_self_index", true)->values;
int index_size = m_print_config.option<ConfigOptionStrings>("filament_extruder_variant")->size();
filament_self_indice.resize(index_size, 1);
int k = 0;
for (size_t i = 0; i < filament_count; i++) {
for (size_t j = 0; j < filament_variant_count[i]; j++) {
filament_self_indice[k++] = i + 1;
}
}
}
}
//compute the flush volume
@ -3082,7 +3189,7 @@ int CLI::run(int argc, char **argv)
std::vector<std::string>& project_filament_colors = project_filament_colors_option->values;
project_filament_colors.resize(filament_count, "#FFFFFF");
}
if (project_filament_colors_option && (selected_filament_colors_option || !m_print_config.option<ConfigOptionFloats>("flush_volumes_matrix")))
if (project_filament_colors_option && (selected_filament_colors_option || !m_print_config.option<ConfigOptionFloats>("flush_volumes_matrix") || (new_extruder_count != current_extruder_count)))
{
std::vector<std::string> selected_filament_colors;
if (selected_filament_colors_option) {
@ -3160,21 +3267,15 @@ int CLI::run(int argc, char **argv)
BOOST_LOG_TRIVIAL(info) << boost::format("flush_volumes_matrix before computing: %1%") % m_print_config.option<ConfigOptionFloats>("flush_volumes_matrix")->serialize();
}
size_t nozzle_nums = 1;
auto opt_nozzle_diameters = m_print_config.option<ConfigOptionFloatsNullable>("nozzle_diameter");
if (opt_nozzle_diameters != nullptr) {
nozzle_nums = opt_nozzle_diameters->values.size();
}
std::vector<double> &flush_vol_matrix = m_print_config.option<ConfigOptionFloats>("flush_volumes_matrix", true)->values;
flush_vol_matrix.resize(project_filament_count * project_filament_count * nozzle_nums, 0.f);
flush_vol_matrix.resize(project_filament_count * project_filament_count * new_extruder_count, 0.f);
// set multiplier to 1?
std::vector<double>& flush_multipliers = m_print_config.option<ConfigOptionFloats>("flush_multiplier", true)->values;
flush_multipliers.resize(nozzle_nums, 1.f);
flush_multipliers.resize(new_extruder_count, 1.f);
for (size_t nozzle_id = 0; nozzle_id < nozzle_nums; ++nozzle_id) {
std::vector<double> flush_vol_mtx = get_flush_volumes_matrix(flush_vol_matrix, nozzle_id, nozzle_nums);
for (size_t nozzle_id = 0; nozzle_id < new_extruder_count; ++nozzle_id) {
std::vector<double> flush_vol_mtx = get_flush_volumes_matrix(flush_vol_matrix, nozzle_id, new_extruder_count);
for (int from_idx = 0; from_idx < project_filament_count; from_idx++) {
const std::string &from_color = project_filament_colors[from_idx];
unsigned char from_rgb[4] = {};
@ -3202,7 +3303,7 @@ int CLI::run(int argc, char **argv)
flush_vol_mtx[project_filament_count * from_idx + to_idx] = flushing_volume;
}
}
set_flush_volumes_matrix(flush_vol_matrix, flush_vol_mtx, nozzle_id, nozzle_nums);
set_flush_volumes_matrix(flush_vol_matrix, flush_vol_mtx, nozzle_id, new_extruder_count);
}
}
BOOST_LOG_TRIVIAL(info) << boost::format("flush_volumes_matrix after computed: %1%")%m_print_config.option<ConfigOptionFloats>("flush_volumes_matrix")->serialize();
@ -3630,7 +3731,7 @@ int CLI::run(int argc, char **argv)
if (downward_settings.size() == 0) {
//parse from internal
std::string cli_config_file = resources_dir() + "/profiles/BBL/cli_config.json";
load_downward_settings_list_from_config(cli_config_file, current_printer_name, current_printer_model, downward_settings);
load_downward_settings_list_from_config(cli_config_file, current_printer_system_name, current_printer_model, downward_settings);
use_default = true;
default_path = resources_dir() + "/profiles/BBL/machine_full/";
}
@ -5341,6 +5442,7 @@ int CLI::run(int argc, char **argv)
long long triangle_count = 0;
int printable_instances = 0;
int skipped_count = 0;
std::vector<std::set<int>> unprintable_filament_ids(new_extruder_count, std::set<int>());
for (ModelObject* model_object : model.objects)
for (ModelInstance *i : model_object->instances)
{
@ -5384,6 +5486,7 @@ int CLI::run(int argc, char **argv)
}
else if (i->print_volume_state == ModelInstancePVS_Inside)
{
const Transform3d& inst_matrix = i->get_transformation().get_matrix();
for (const ModelVolume* vol : model_object->volumes)
{
if (vol->is_model_part()) {
@ -5396,6 +5499,21 @@ int CLI::run(int argc, char **argv)
record_exit_reson(outfile_dir, CLI_TRIANGLE_COUNT_EXCEEDS_LIMIT, index+1, cli_errors[CLI_TRIANGLE_COUNT_EXCEEDS_LIMIT], sliced_info);
flush_and_exit(CLI_TRIANGLE_COUNT_EXCEEDS_LIMIT);
}
if (new_extruder_count > 1) {
BoundingBoxf3 bbox = vol->get_convex_hull().transformed_bounding_box(inst_matrix * vol->get_matrix());
std::vector<bool> inside_extruders;
BuildVolume::ObjectState state = build_volume.check_volume_bbox_state_with_extruder_areas(bbox, inside_extruders);
if (state == BuildVolume::ObjectState::Limited) {
for (size_t i = 0; i < inside_extruders.size(); ++i) {
if (!inside_extruders[i]) {
std::vector<int> filaments = vol->get_extruders();
unprintable_filament_ids[i].insert(filaments.begin(), filaments.end());
}
}
}
}
}
}
}
@ -5410,6 +5528,69 @@ int CLI::run(int argc, char **argv)
flush_and_exit(CLI_NO_SUITABLE_OBJECTS_AFTER_SKIP);
}
if (new_extruder_count > 1) {
std::vector<std::vector<int>> unprintable_filament_vec;
for (const std::set<int>& filamnt_ids : unprintable_filament_ids) {
unprintable_filament_vec.emplace_back(std::vector<int>(filamnt_ids.begin(), filamnt_ids.end()));
}
FilamentMapMode mode;
if (m_extra_config.option<ConfigOptionEnum<FilamentMapMode>>("filament_map_mode"))
mode = m_extra_config.option<ConfigOptionEnum<FilamentMapMode>>("filament_map_mode")->value;
else
mode = part_plate->get_filament_map_mode();
if (mode == FilamentMapMode::fmmAuto) {
part_plate->set_unprintable_filament_ids(unprintable_filament_vec);
std::vector<int> conflict_filament_vector;
for (int index = 0; index < new_extruder_count; index++)
{
if (!unprintable_filament_vec[index].empty())
{
std::sort(unprintable_filament_vec[index].begin(), unprintable_filament_vec[index].end());
if (index == 0)
conflict_filament_vector = unprintable_filament_vec[index];
else
{
std::vector<int> result_filaments;
//result_filaments.reserve(conflict_filaments.size());
std::set_intersection(conflict_filament_vector.begin(), conflict_filament_vector.end(), unprintable_filament_vec[index].begin(),
unprintable_filament_vec[index].end(), insert_iterator<vector<int>>(result_filaments, result_filaments.begin()));
conflict_filament_vector = result_filaments;
}
}
else
{
conflict_filament_vector.clear();
break;
}
}
//check whether has filament can not map
if (!conflict_filament_vector.empty())
{
BOOST_LOG_TRIVIAL(error) << boost::format("plate %1% : some filaments can not be mapped under auto mode for multi extruder printer ")% (index + 1);
record_exit_reson(outfile_dir, CLI_FILAMENT_CAN_NOT_MAP, index + 1, cli_errors[CLI_FILAMENT_CAN_NOT_MAP], sliced_info);
flush_and_exit(CLI_FILAMENT_CAN_NOT_MAP);
}
}
else {
std::vector<int> filament_maps;
if (m_extra_config.option<ConfigOptionInts>("filament_map"))
filament_maps = m_extra_config.option<ConfigOptionInts>("filament_map")->values;
else
filament_maps = part_plate->get_filament_maps();
for (int index = 0; index < filament_maps.size(); index++)
{
int filament_extruder = filament_maps[index];
if (unprintable_filament_ids[filament_extruder - 1].find(index + 1) != unprintable_filament_ids[filament_extruder - 1].end())
{
BOOST_LOG_TRIVIAL(error) << boost::format("plate %1% : some filaments can not be mapped under auto mode for multi extruder printer ") % (index + 1);
record_exit_reson(outfile_dir, CLI_FILAMENT_CAN_NOT_MAP, index + 1, cli_errors[CLI_FILAMENT_CAN_NOT_MAP], sliced_info);
flush_and_exit(CLI_FILAMENT_CAN_NOT_MAP);
}
}
}
}
plate_triangle_counts[index] = triangle_count;
plate_object_count[index] = printable_instances;
BOOST_LOG_TRIVIAL(info) << "plate "<< index+1<< ": load cached data success, go on.";
@ -5421,6 +5602,35 @@ int CLI::run(int argc, char **argv)
DynamicPrintConfig new_print_config = m_print_config;
new_print_config.apply(*part_plate->config());
new_print_config.apply(m_extra_config, true);
if (new_extruder_count > 1) {
FilamentMapMode map_mode = fmmAuto;
if (new_print_config.option<ConfigOptionEnum<FilamentMapMode>>("filament_map_mode"))
map_mode = new_print_config.option<ConfigOptionEnum<FilamentMapMode>>("filament_map_mode")->value;
if (map_mode == fmmAuto) {
//set default params for auto map
std::vector<std::string> extruder_ams_count(new_extruder_count, "");
std::vector<std::vector<DynamicPrintConfig>> extruder_filament_info(new_extruder_count, std::vector<DynamicPrintConfig>());
int color_count = 0;
for (int e_index = 0; e_index < new_extruder_count; e_index++)
{
extruder_ams_count[e_index] = "1#0|4#1";
for (int color_index = 0; color_index < 4; color_index++)
{
DynamicPrintConfig temp_config;
std::vector<std::string> temp_colors(1, "#FFFFFFFF");
if (filament_color) {
temp_colors[0] = colors[color_count % colors.size()];
}
temp_config.option<ConfigOptionStrings>("filament_colour", true)->values = temp_colors;
extruder_filament_info[e_index].push_back(std::move(temp_config));
color_count++;
}
}
new_print_config.option<ConfigOptionStrings>("extruder_ams_count", true)->values = extruder_ams_count;
print_fff->set_extruder_filament_info(extruder_filament_info);
}
}
print->apply(model, new_print_config);
BOOST_LOG_TRIVIAL(info) << boost::format("set no_check to %1%:")%no_check;
print->set_no_check_flag(no_check);//BBS
@ -5638,6 +5848,13 @@ int CLI::run(int argc, char **argv)
slice_time[TIME_USING_CACHE] = slice_time[TIME_USING_CACHE] + ((long long)Slic3r::Utils::get_current_milliseconds_time_utc() - temp_time);
BOOST_LOG_TRIVIAL(info) << "export_gcode finished: time_using_cache update to " << slice_time[TIME_USING_CACHE] << " secs.";
if (gcode_result && gcode_result->gcode_check_result.error_code) {
//found gcode error
BOOST_LOG_TRIVIAL(error) << "plate " << index + 1 << ": found gcode in unprintable area of multi extruder printers!" << std::endl;
record_exit_reson(outfile_dir, CLI_GCODE_PATH_IN_UNPRINTABLE_AREA, index + 1, cli_errors[CLI_GCODE_PATH_IN_UNPRINTABLE_AREA], sliced_info);
flush_and_exit(CLI_GCODE_PATH_IN_UNPRINTABLE_AREA);
}
if (gcode_result && gcode_result->filament_printable_reuslt.has_value()) {
//found gcode error
BOOST_LOG_TRIVIAL(error) << "plate " << index + 1 << ": found some filament unprintable on current bed- "<< gcode_result->filament_printable_reuslt.plate_name << std::endl;

View File

@ -147,6 +147,8 @@ BuildVolume::BuildVolume(const std::vector<Vec2d> &printable_area, const double
extruder_volume.bboxf = m_bboxf;
extruder_volume.circle = m_circle;
}
//always ignore z
extruder_volume.bboxf.min.z() = -std::numeric_limits<double>::max();
m_extruder_volumes.push_back(std::move(extruder_volume));
}

View File

@ -3201,7 +3201,6 @@ void PrintConfigDef::init_fff_params()
def->label = "Extruder ams count";
def->tooltip = "Ams counts of per extruder";
def->set_default_value(new ConfigOptionStrings { });
def->cli = ConfigOptionDef::nocli;
def = this->add("printer_extruder_id", coInts);
def->label = "Printer extruder id";
@ -5204,12 +5203,12 @@ std::set<std::string> print_options_with_variant = {
"initial_layer_infill_speed",
"outer_wall_speed",
"inner_wall_speed",
"small_perimeter_speed",
"small_perimeter_speed", //coFloatsOrPercents
"small_perimeter_threshold",
"sparse_infill_speed",
"internal_solid_infill_speed",
"top_surface_speed",
"enable_overhang_speed",
"enable_overhang_speed", //coBools
"overhang_1_4_speed",
"overhang_2_4_speed",
"overhang_3_4_speed",
@ -5224,10 +5223,10 @@ std::set<std::string> print_options_with_variant = {
"initial_layer_acceleration",
"outer_wall_acceleration",
"inner_wall_acceleration",
"sparse_infill_acceleration",
"sparse_infill_acceleration", //coFloatsOrPercents
"top_surface_acceleration",
"print_extruder_id",
"print_extruder_variant"
"print_extruder_id", //coInts
"print_extruder_variant" //coStrings
};
std::set<std::string> filament_options_with_variant = {
@ -5780,6 +5779,210 @@ int DynamicPrintConfig::get_index_for_extruder(int extruder_or_filament_id, std:
return ret;
}
//only used for cli
//update values in single extruder process config to values in multi-extruder process
//limit the new values
int DynamicPrintConfig::update_values_from_single_to_multi(DynamicPrintConfig& multi_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name)
{
auto print_variant_opt = dynamic_cast<const ConfigOptionStrings*>(multi_config.option(variant_name));
if (!print_variant_opt) {
BOOST_LOG_TRIVIAL(error) << boost::format("%1%:%2%, can not get %3% from config")%__FUNCTION__ %__LINE__ % variant_name;
return -1;
}
int variant_count = print_variant_opt->size();
const ConfigDef *config_def = this->def();
if (!config_def) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: can not find config define")%__LINE__;
return -1;
}
for (auto& key: key_set)
{
const ConfigOptionDef *optdef = config_def->get(key);
if (!optdef) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: can not find opt define for %2%")%__LINE__%key;
continue;
}
switch (optdef->type) {
case coStrings:
{
ConfigOptionStrings * opt = this->option<ConfigOptionStrings>(key);
ConfigOptionStrings * src_opt = multi_config.option<ConfigOptionStrings>(key);
opt->values = src_opt->values;
break;
}
case coInts:
{
ConfigOptionInts * opt = this->option<ConfigOptionInts>(key);
ConfigOptionInts * src_opt = multi_config.option<ConfigOptionInts>(key);
opt->values = src_opt->values;
break;
}
case coFloats:
{
ConfigOptionFloats * opt = this->option<ConfigOptionFloats>(key);
ConfigOptionFloats * src_opt = multi_config.option<ConfigOptionFloats>(key);
assert(variant_count == src_opt->size());
opt->resize(variant_count, opt);
for (int index = 0; index < variant_count; index++)
{
if (opt->values[index] > src_opt->values[index])
opt->values[index] = src_opt->values[index];
}
break;
}
case coFloatsOrPercents:
{
ConfigOptionFloatsOrPercents * opt = this->option<ConfigOptionFloatsOrPercents>(key);
ConfigOptionFloatsOrPercents * src_opt = multi_config.option<ConfigOptionFloatsOrPercents>(key);
assert(variant_count == src_opt->size());
opt->resize(variant_count, opt);
for (int index = 0; index < variant_count; index++)
{
if (opt->values[index].value > src_opt->values[index].value)
opt->values[index] = src_opt->values[index];
}
break;
}
case coBools:
{
ConfigOptionBools * opt = this->option<ConfigOptionBools>(key);
ConfigOptionBools * src_opt = multi_config.option<ConfigOptionBools>(key);
assert(variant_count == src_opt->size());
opt->resize(variant_count, opt);
break;
}
default:
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: unsupported option type for %2%")%__LINE__%key;
break;
}
}
return 0;
}
int DynamicPrintConfig::update_values_from_multi_to_single(DynamicPrintConfig& single_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name, std::vector<std::string>& extruder_variants)
{
int extruder_count = extruder_variants.size();
std::vector<int> extruder_index(extruder_count, -1);
auto print_variant_opt = dynamic_cast<const ConfigOptionStrings*>(this->option(variant_name));
if (!print_variant_opt) {
BOOST_LOG_TRIVIAL(error) << boost::format("%1%:%2%, can not get %3% from config")%__FUNCTION__ %__LINE__ % variant_name;
return -1;
}
int variant_count = print_variant_opt->size();
auto print_id_opt = dynamic_cast<const ConfigOptionInts*>(this->option(id_name));
if (!print_id_opt) {
BOOST_LOG_TRIVIAL(error) << boost::format("%1%:%2%, can not get %3% from config")%__FUNCTION__ %__LINE__ % id_name;
return -1;
}
for (int i = 0; i < extruder_count; i++)
{
for (int j = 0; j < variant_count; j++)
{
if ((i+1 == print_id_opt->values[j]) && (extruder_variants[i] == print_variant_opt->values[j])) {
extruder_index[i] = j;
break;
}
}
}
const ConfigDef* config_def = this->def();
if (!config_def) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: can not find config define") % __LINE__;
return -1;
}
for (auto& key : key_set)
{
const ConfigOptionDef* optdef = config_def->get(key);
if (!optdef) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: can not find opt define for %2%") % __LINE__ % key;
continue;
}
switch (optdef->type) {
case coStrings:
{
ConfigOptionStrings* opt = this->option<ConfigOptionStrings>(key);
ConfigOptionStrings* src_opt = single_config.option<ConfigOptionStrings>(key);
assert(variant_count == opt->size());
opt->values = src_opt->values;
break;
}
case coInts:
{
ConfigOptionInts* opt = this->option<ConfigOptionInts>(key);
ConfigOptionInts* src_opt = single_config.option<ConfigOptionInts>(key);
assert(variant_count == opt->size());
opt->values = src_opt->values;
break;
}
case coFloats:
{
ConfigOptionFloats* opt = this->option<ConfigOptionFloats>(key);
ConfigOptionFloats* src_opt = single_config.option<ConfigOptionFloats>(key);
std::vector<double> old_values = opt->values;
assert(variant_count == opt->size());
opt->values = src_opt->values;
for (int i = 0; i < extruder_count; i++)
{
assert(extruder_index[i] != -1);
if (old_values[extruder_index[i]] < opt->values[0])
opt->values[0] = old_values[extruder_index[i]];
}
break;
}
case coFloatsOrPercents:
{
ConfigOptionFloatsOrPercents* opt = this->option<ConfigOptionFloatsOrPercents>(key);
ConfigOptionFloatsOrPercents* src_opt = single_config.option<ConfigOptionFloatsOrPercents>(key);
std::vector<FloatOrPercent> old_values = opt->values;
assert(variant_count == opt->size());
opt->values = src_opt->values;
for (int i = 0; i < extruder_count; i++)
{
assert(extruder_index[i] != -1);
if (old_values[extruder_index[i]].value < opt->values[0].value)
opt->values[0] = old_values[extruder_index[i]];
}
break;
}
case coBools:
{
ConfigOptionBools* opt = this->option<ConfigOptionBools>(key);
ConfigOptionBools* src_opt = single_config.option<ConfigOptionBools>(key);
assert(variant_count == opt->size());
opt->values = src_opt->values;
break;
}
default:
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: unsupported option type for %2%") % __LINE__ % key;
break;
}
}
return 0;
}
std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name, unsigned int stride, unsigned int extruder_id)
{
int extruder_count;
@ -5851,7 +6054,7 @@ std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicP
new_values.resize(extruder_count * stride);
for (int e_index = 0; e_index < extruder_count; e_index++)
{
for (int i = 0; i < stride; i++)
for (unsigned int i = 0; i < stride; i++)
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
}
opt->values = new_values;
@ -5865,7 +6068,7 @@ std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicP
new_values.resize(extruder_count * stride);
for (int e_index = 0; e_index < extruder_count; e_index++)
{
for (int i = 0; i < stride; i++)
for (unsigned int i = 0; i < stride; i++)
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
}
opt->values = new_values;
@ -5879,7 +6082,7 @@ std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicP
new_values.resize(extruder_count * stride);
for (int e_index = 0; e_index < extruder_count; e_index++)
{
for (int i = 0; i < stride; i++)
for (unsigned int i = 0; i < stride; i++)
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
}
opt->values = new_values;
@ -5893,7 +6096,7 @@ std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicP
new_values.resize(extruder_count * stride);
for (int e_index = 0; e_index < extruder_count; e_index++)
{
for (int i = 0; i < stride; i++)
for (unsigned int i = 0; i < stride; i++)
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
}
opt->values = new_values;
@ -5907,7 +6110,7 @@ std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicP
new_values.resize(extruder_count * stride);
for (int e_index = 0; e_index < extruder_count; e_index++)
{
for (int i = 0; i < stride; i++)
for (unsigned int i = 0; i < stride; i++)
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
}
opt->values = new_values;
@ -5921,7 +6124,7 @@ std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicP
new_values.resize(extruder_count * stride);
for (int e_index = 0; e_index < extruder_count; e_index++)
{
for (int i = 0; i < stride; i++)
for (unsigned int i = 0; i < stride; i++)
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
}
opt->values = new_values;
@ -5935,7 +6138,7 @@ std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicP
new_values.resize(extruder_count * stride);
for (int e_index = 0; e_index < extruder_count; e_index++)
{
for (int i = 0; i < stride; i++)
for (unsigned int i = 0; i < stride; i++)
new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i);
}
opt->values = new_values;
@ -5953,7 +6156,7 @@ std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicP
void DynamicPrintConfig::update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name)
{
int extruder_count, filament_count;
int extruder_count;
bool different_extruder = printer_config.support_different_extruders(extruder_count);
if ((extruder_count > 1) || different_extruder)
{
@ -7019,9 +7222,26 @@ static Points to_points(const std::vector<Vec2d> &dpts)
return pts;
}
Points get_bed_shape(const DynamicPrintConfig &config)
static Polygon get_shared_poly(const std::vector<Pointfs>& extruder_polys)
{
const auto *bed_shape_opt = config.opt<ConfigOptionPoints>("printable_area");
Polygon result;
for (int index = 0; index < extruder_polys.size(); index++)
{
const Pointfs& extruder_area = extruder_polys[index];
if (index == 0)
result.points = to_points(extruder_area);
else {
Polygon extruer_poly;
extruer_poly.points = to_points(extruder_area);
Polygons result_polygon = intersection(extruer_poly, result);
result = result_polygon[0];
}
}
return result;
}
Points get_bed_shape(const DynamicPrintConfig &config, bool use_share)
{
const ConfigOptionPoints *bed_shape_opt = config.opt<ConfigOptionPoints>("printable_area");
if (!bed_shape_opt) {
// Here, it is certain that the bed shape is missing, so an infinite one
@ -7032,20 +7252,45 @@ Points get_bed_shape(const DynamicPrintConfig &config)
return {};
}
return to_points(bed_shape_opt->values);
Polygon bed_poly;
if (use_share) {
const ConfigOptionPointsGroups *extruder_area_opt = config.opt<ConfigOptionPointsGroups>("extruder_printable_area");
if (extruder_area_opt && (extruder_area_opt->size() > 0)) {
const std::vector<Pointfs>& extruder_areas = extruder_area_opt->values;
bed_poly = get_shared_poly(extruder_areas);
}
else
bed_poly.points = to_points(bed_shape_opt->values);
}
else
bed_poly.points = to_points(bed_shape_opt->values);
return bed_poly.points;
}
Points get_bed_shape(const PrintConfig &cfg)
Points get_bed_shape(const PrintConfig &cfg, bool use_share)
{
return to_points(cfg.printable_area.values);
Polygon bed_poly;
if (use_share) {
const std::vector<Pointfs>& extruder_areas = cfg.extruder_printable_area.values;
if (extruder_areas.size() > 0) {
bed_poly = get_shared_poly(extruder_areas);
}
else
bed_poly.points = to_points(cfg.printable_area.values);
}
else
bed_poly.points = to_points(cfg.printable_area.values);
return bed_poly.points;
}
Points get_bed_shape(const SLAPrinterConfig &cfg) { return to_points(cfg.printable_area.values); }
Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg)
Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg, bool use_share)
{
Polygon bed_poly;
bed_poly.points = get_bed_shape(cfg);
bed_poly.points = get_bed_shape(cfg, use_share);
Points excluse_area_points = to_points(cfg.bed_exclude_area.values);
Polygons exclude_polys;

View File

@ -509,6 +509,9 @@ public:
std::set<std::string>& key_set1, std::set<std::string>& key_set2);
void update_diff_values_to_child_config(DynamicPrintConfig& new_config, std::string extruder_id_name, std::string extruder_variant_name, std::set<std::string>& key_set1, std::set<std::string>& key_set2);
int update_values_from_single_to_multi(DynamicPrintConfig& multi_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name);
int update_values_from_multi_to_single(DynamicPrintConfig& single_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name, std::vector<std::string>& extruder_variants);
};
extern std::set<std::string> printer_extruder_options;
extern std::set<std::string> print_options_with_variant;
@ -1482,10 +1485,10 @@ private:
static PrintAndCLIConfigDef s_def;
};
Points get_bed_shape(const DynamicPrintConfig &cfg);
Points get_bed_shape(const PrintConfig &cfg);
Points get_bed_shape(const DynamicPrintConfig &cfg, bool use_share = true);
Points get_bed_shape(const PrintConfig &cfg, bool use_share = false);
Points get_bed_shape(const SLAPrinterConfig &cfg);
Slic3r::Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg);
Slic3r::Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg, bool use_share = false);
bool has_skirt(const DynamicPrintConfig& cfg);
float get_real_skirt_dist(const DynamicPrintConfig& cfg);

View File

@ -60,9 +60,11 @@
#define CLI_OBJECT_COLLISION_IN_SEQ_PRINT -63
#define CLI_OBJECT_COLLISION_IN_LAYER_PRINT -64
#define CLI_SPIRAL_MODE_INVALID_PARAMS -65
#define CLI_FILAMENT_CAN_NOT_MAP -66
#define CLI_SLICING_ERROR -100
#define CLI_GCODE_PATH_CONFLICTS -101
#define CLI_GCODE_PATH_IN_UNPRINTABLE_AREA -102
#define CLI_FILAMENT_UNPRINTABLE_ON_FIRST_LAYER -103