mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-11 11:07:40 +00:00
X2D Support (#13388)
# Description Adresses #13294 - Adds the X2D printer definition, machine presets, process presets, filament presets, BBL profile index entries, CLI config entries, filament blacklist updates, and printer/load/calibration/cover assets. - Updates dual-nozzle handling to use configured toolhead labels and match Bambu X2D hotend placeholders. - Adds X2D-specific wipe tower cooling placeholder support and 3MF filament/nozzle change sequence metadata import/export plumbing. # Note I own a P2S and an X2D. That's all. I frankly have no idea if my changes cause regression on other printers, and have no capability to test. I know that for my X2D, which runs an AMS, .2mm nozzles, SuperTack, and in LAN mode, this has been working without issue. # Screenshots/Recordings/Graphs <img width="606" height="380" alt="Dual nozzle control" src="https://github.com/user-attachments/assets/0d1c1063-4621-4097-b97c-d739557bf18c" /> *Dual nozzle control* <img width="726" height="260" alt="image" src="https://github.com/user-attachments/assets/270355b7-ca67-4ca3-ad19-582b8f11411b" /> *Multi nozzle filament override* <img width="416" height="202" alt="X2D Machine config and dual nozzle support" src="https://github.com/user-attachments/assets/6a5c07b2-0d20-4819-8f42-d60731313249" /> *X2D Machine config and dual nozzle support* <img width="397" height="142" alt="Filament for Supports test prints" src="https://github.com/user-attachments/assets/3c7546bd-0e27-4d56-89b7-d9ca18c976f9" /> *Filament for Supports has been used in over 20 hours of test prints* <img width="210" height="263" alt="Left vs Right filament distinction" src="https://github.com/user-attachments/assets/03322268-b669-4f14-8d77-c4d96843d219" /> *Left vs Right filament distinction* <img width="557" height="327" alt="Custom filament mapping" src="https://github.com/user-attachments/assets/c1c4396f-7359-474e-80bd-78fec22f9c82" /> *Custom filament mapping* <img width="556" height="314" alt="Auto map" src="https://github.com/user-attachments/assets/d83e3217-edce-4340-886e-043962003a30" /> *Auto map* <img width="689" height="664" alt="LAN mode send print with X2D preview and no errors" src="https://github.com/user-attachments/assets/76009bbf-31d3-4a6c-979c-8643b487c824" /> *LAN mode send print with X2D preview and no errors, dual nozzle selection* ## Tests - 20 hours of dual-nozzle printing. - 100% CTest tests passed - Validated 208 changed JSON files. <!-- > A guide for users on how to download the artifacts from this PR. --> [How to Download Pull Requests Artifacts for Testing](https://www.orcaslicer.com/wiki/how_to_download_pr_artifacts) Fix #13294
This commit is contained in:
@@ -210,6 +210,7 @@ const std::string BBS_PROJECT_CONFIG_FILE = "Metadata/project_settings.config";
|
||||
const std::string BBS_MODEL_CONFIG_FILE = "Metadata/model_settings.config";
|
||||
const std::string BBS_MODEL_CONFIG_RELS_FILE = "Metadata/_rels/model_settings.config.rels";
|
||||
const std::string SLICE_INFO_CONFIG_FILE = "Metadata/slice_info.config";
|
||||
const std::string FILAMENT_SEQUENCE_FILE = "Metadata/filament_sequence.json";
|
||||
const std::string BBS_LAYER_HEIGHTS_PROFILE_FILE = "Metadata/layer_heights_profile.txt";
|
||||
const std::string LAYER_CONFIG_RANGES_FILE = "Metadata/layer_config_ranges.xml";
|
||||
const std::string BRIM_EAR_POINTS_FILE = "Metadata/brim_ear_points.txt";
|
||||
@@ -251,6 +252,12 @@ static constexpr const char* FILAMENT_TYPE_TAG = "type";
|
||||
static constexpr const char *FILAMENT_COLOR_TAG = "color";
|
||||
static constexpr const char *FILAMENT_USED_M_TAG = "used_m";
|
||||
static constexpr const char *FILAMENT_USED_G_TAG = "used_g";
|
||||
static constexpr const char *FILAMENT_USED_FOR_SUPPORT = "used_for_support";
|
||||
static constexpr const char *FILAMENT_USED_FOR_OBJECT = "used_for_object";
|
||||
static constexpr const char *FILAMENT_NOZZLE_GROUP_ID_TAG = "group_id";
|
||||
static constexpr const char *FILAMENT_NOZZLE_DIAMETER_TAG = "nozzle_diameter";
|
||||
static constexpr const char *FILAMENT_NOZZLE_VOLUME_TYPE_TAG = "volume_type";
|
||||
static constexpr const char *NOZZLE_TAG = "nozzle";
|
||||
static constexpr const char *FILAMENT_TRAY_INFO_ID_TAG = "tray_info_idx";
|
||||
static constexpr const char *LAYER_FILAMENT_LISTS_TAG = "layer_filament_lists";
|
||||
static constexpr const char *LAYER_FILAMENT_LIST_TAG = "layer_filament_list";
|
||||
@@ -365,6 +372,8 @@ static constexpr const char* TIMELAPSE_TYPE_ATTR = "timelapse_type";
|
||||
static constexpr const char* OUTSIDE_ATTR = "outside";
|
||||
static constexpr const char* SUPPORT_USED_ATTR = "support_used";
|
||||
static constexpr const char* LABEL_OBJECT_ENABLED_ATTR = "label_object_enabled";
|
||||
static constexpr const char* ENABLE_FILAMENT_DYNAMIC_MAP_ATTR = "enable_filament_dynamic_map";
|
||||
static constexpr const char* HAS_FILAMENT_SWITCHER_ATTR = "has_filament_switcher";
|
||||
static constexpr const char* SKIPPED_ATTR = "skipped";
|
||||
|
||||
static constexpr const char* OBJECT_TYPE = "object";
|
||||
@@ -528,6 +537,40 @@ void add_vector(std::stringstream &stream, const std::vector<T> &values)
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> parse_int_list(const std::string& value)
|
||||
{
|
||||
std::vector<int> out;
|
||||
if (value.empty())
|
||||
return out;
|
||||
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, value, boost::is_any_of(" ,"), boost::token_compress_on);
|
||||
out.reserve(tokens.size());
|
||||
for (const std::string& token : tokens) {
|
||||
if (token.empty())
|
||||
continue;
|
||||
try {
|
||||
out.emplace_back(boost::lexical_cast<int>(token));
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(out.begin(), out.end());
|
||||
out.erase(std::unique(out.begin(), out.end()), out.end());
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string join_int_list_comma(const std::vector<int>& values)
|
||||
{
|
||||
std::stringstream stream;
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
stream << values[i];
|
||||
if (i + 1 < values.size())
|
||||
stream << ",";
|
||||
}
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
Slic3r::Vec3f get_vec3_from_string(const std::string &pos_str)
|
||||
{
|
||||
Slic3r::Vec3f pos(0, 0, 0);
|
||||
@@ -655,6 +698,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
info.id = it->first;
|
||||
info.used_g = used_filament_g;
|
||||
info.used_m = used_filament_m;
|
||||
auto model_volume_it = ps.model_volumes_per_extruder.find(it->first);
|
||||
auto support_volume_it = ps.support_volumes_per_extruder.find(it->first);
|
||||
info.used_for_object = model_volume_it != ps.model_volumes_per_extruder.end() && model_volume_it->second > EPSILON;
|
||||
info.used_for_support = support_volume_it != ps.support_volumes_per_extruder.end() && support_volume_it->second > EPSILON;
|
||||
slice_filaments_info.push_back(info);
|
||||
}
|
||||
|
||||
@@ -1142,6 +1189,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
void _extract_brim_ear_points_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
|
||||
void _extract_custom_gcode_per_print_z_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
void _extract_filament_sequence_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
|
||||
void _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config, ConfigSubstitutionContext& subs_context, const std::string& archive_filename);
|
||||
//BBS: add project config file logic
|
||||
@@ -1535,6 +1583,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
_extract_xml_from_archive(archive, stat, _handle_start_config_xml_element, _handle_end_config_xml_element);
|
||||
m_parsing_slice_info = false;
|
||||
}
|
||||
else if (boost::algorithm::iequals(name, FILAMENT_SEQUENCE_FILE)) {
|
||||
_extract_filament_sequence_from_archive(archive, stat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1568,6 +1619,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
plate->slice_filaments_info = it->second->slice_filaments_info;
|
||||
plate->printer_model_id = it->second->printer_model_id;
|
||||
plate->nozzle_diameters = it->second->nozzle_diameters;
|
||||
plate->filament_maps = it->second->filament_maps;
|
||||
plate->filament_change_sequence = it->second->filament_change_sequence;
|
||||
plate->nozzle_change_sequence = it->second->nozzle_change_sequence;
|
||||
plate->optimal_assignment = it->second->optimal_assignment;
|
||||
plate->warnings = it->second->warnings;
|
||||
plate->thumbnail_file = it->second->thumbnail_file;
|
||||
if (plate->thumbnail_file.empty()) {
|
||||
@@ -1911,6 +1966,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
_extract_xml_from_archive(archive, stat, _handle_start_config_xml_element, _handle_end_config_xml_element);
|
||||
m_parsing_slice_info = false;
|
||||
}
|
||||
else if (!dont_load_config && boost::algorithm::iequals(name, FILAMENT_SEQUENCE_FILE)) {
|
||||
_extract_filament_sequence_from_archive(archive, stat);
|
||||
}
|
||||
else if (boost::algorithm::istarts_with(name, AUXILIARY_DIR)) {
|
||||
// extract auxiliary directory to temp directory, do nothing for restore
|
||||
if (m_load_aux && !m_load_restore)
|
||||
@@ -2231,6 +2289,12 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
plate_data_list[it->first-1]->is_label_object_enabled = it->second->is_label_object_enabled;
|
||||
plate_data_list[it->first-1]->slice_filaments_info = it->second->slice_filaments_info;
|
||||
plate_data_list[it->first-1]->skipped_objects = it->second->skipped_objects;
|
||||
plate_data_list[it->first-1]->printer_model_id = it->second->printer_model_id;
|
||||
plate_data_list[it->first-1]->nozzle_diameters = it->second->nozzle_diameters;
|
||||
plate_data_list[it->first-1]->filament_maps = it->second->filament_maps;
|
||||
plate_data_list[it->first-1]->filament_change_sequence = it->second->filament_change_sequence;
|
||||
plate_data_list[it->first-1]->nozzle_change_sequence = it->second->nozzle_change_sequence;
|
||||
plate_data_list[it->first-1]->optimal_assignment = it->second->optimal_assignment;
|
||||
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;
|
||||
@@ -3226,6 +3290,62 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
}
|
||||
}
|
||||
|
||||
void _BBS_3MF_Importer::_extract_filament_sequence_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat)
|
||||
{
|
||||
if (stat.m_uncomp_size == 0) {
|
||||
add_error("Error while reading filament sequence data to buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string buffer((size_t) stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*) buffer.data(), (size_t) stat.m_uncomp_size, 0);
|
||||
if (res == 0) {
|
||||
add_error("Error while reading filament sequence data to buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const nlohmann::json sequence_json = nlohmann::json::parse(buffer);
|
||||
for (auto& elem : m_plater_data) {
|
||||
const std::string plate_key = "plate_" + std::to_string(elem.first);
|
||||
auto plate_it = sequence_json.find(plate_key);
|
||||
if (plate_it == sequence_json.end() || !plate_it->is_object())
|
||||
continue;
|
||||
|
||||
auto filament_it = plate_it->find("filament_sequence");
|
||||
if (filament_it == plate_it->end())
|
||||
filament_it = plate_it->find("sequence");
|
||||
|
||||
auto nozzle_it = plate_it->find("nozzle_sequence");
|
||||
if (filament_it == plate_it->end() || !filament_it->is_array() || nozzle_it == plate_it->end() || !nozzle_it->is_array())
|
||||
continue;
|
||||
|
||||
std::vector<unsigned int> filament_sequence;
|
||||
std::vector<unsigned int> nozzle_sequence;
|
||||
std::vector<int> optimal_assignment;
|
||||
for (const auto& item : *filament_it) {
|
||||
const unsigned int filament_id = item.get<unsigned int>();
|
||||
filament_sequence.push_back(filament_id > 0 ? filament_id - 1 : 0);
|
||||
}
|
||||
for (const auto& item : *nozzle_it)
|
||||
nozzle_sequence.push_back(item.get<unsigned int>());
|
||||
|
||||
auto optimal_assignment_it = plate_it->find("optimal_assignment");
|
||||
if (optimal_assignment_it != plate_it->end() && optimal_assignment_it->is_array()) {
|
||||
for (const auto& item : *optimal_assignment_it)
|
||||
optimal_assignment.emplace_back(item.get<int>());
|
||||
}
|
||||
|
||||
elem.second->filament_change_sequence = std::move(filament_sequence);
|
||||
elem.second->nozzle_change_sequence = std::move(nozzle_sequence);
|
||||
if (!optimal_assignment.empty())
|
||||
elem.second->optimal_assignment = std::move(optimal_assignment);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
add_error(std::string("Error while parsing filament sequence JSON: ") + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void _BBS_3MF_Importer::_handle_start_model_xml_element(const char* name, const char** attributes)
|
||||
{
|
||||
if (m_xml_parser == nullptr)
|
||||
@@ -4294,7 +4414,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
else if (key == BED_TYPE_ATTR)
|
||||
{
|
||||
BedType bed_type = BedType::btPC;
|
||||
ConfigOptionEnum<BedType>::from_string(value, bed_type);
|
||||
const std::string bed_type_value = value == "SuperTack Plate" ? "Supertack Plate" : value;
|
||||
ConfigOptionEnum<BedType>::from_string(bed_type_value, bed_type);
|
||||
m_curr_plater->config.set_key_value("curr_bed_type", new ConfigOptionEnum<BedType>(bed_type));
|
||||
}
|
||||
else if (key == PRINT_SEQUENCE_ATTR)
|
||||
@@ -4334,6 +4455,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
filament_map[idx] = 1;
|
||||
}
|
||||
}
|
||||
m_curr_plater->filament_maps = filament_map;
|
||||
m_curr_plater->config.set_key_value("filament_map", new ConfigOptionInts(filament_map));
|
||||
}
|
||||
}
|
||||
@@ -4425,6 +4547,22 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
if (m_curr_plater)
|
||||
std::istringstream(value) >> std::boolalpha >> m_curr_plater->is_label_object_enabled;
|
||||
}
|
||||
else if (key == ENABLE_FILAMENT_DYNAMIC_MAP_ATTR)
|
||||
{
|
||||
if (m_curr_plater) {
|
||||
bool enable_filament_dynamic_map = false;
|
||||
std::istringstream(value) >> std::boolalpha >> enable_filament_dynamic_map;
|
||||
m_curr_plater->config.set_key_value("enable_filament_dynamic_map", new ConfigOptionBool(enable_filament_dynamic_map));
|
||||
}
|
||||
}
|
||||
else if (key == HAS_FILAMENT_SWITCHER_ATTR)
|
||||
{
|
||||
if (m_curr_plater) {
|
||||
bool has_filament_switcher = false;
|
||||
std::istringstream(value) >> std::boolalpha >> has_filament_switcher;
|
||||
m_curr_plater->config.set_key_value("has_filament_switcher", new ConfigOptionBool(has_filament_switcher));
|
||||
}
|
||||
}
|
||||
else if (key == PRINTER_MODEL_ID_ATTR)
|
||||
{
|
||||
if (m_curr_plater)
|
||||
@@ -4455,6 +4593,11 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
std::string used_m = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_USED_M_TAG);
|
||||
std::string used_g = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_USED_G_TAG);
|
||||
std::string filament_id = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_TRAY_INFO_ID_TAG);
|
||||
std::string used_for_object = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_USED_FOR_OBJECT);
|
||||
std::string used_for_support = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_USED_FOR_SUPPORT);
|
||||
std::string group_id = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_NOZZLE_GROUP_ID_TAG);
|
||||
std::string nozzle_diameter = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_NOZZLE_DIAMETER_TAG);
|
||||
std::string volume_type = bbs_get_attribute_value_string(attributes, num_attributes, FILAMENT_NOZZLE_VOLUME_TYPE_TAG);
|
||||
FilamentInfo filament_info;
|
||||
filament_info.id = atoi(id.c_str()) - 1;
|
||||
filament_info.type = type;
|
||||
@@ -4462,6 +4605,11 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
filament_info.used_m = atof(used_m.c_str());
|
||||
filament_info.used_g = atof(used_g.c_str());
|
||||
filament_info.filament_id = filament_id;
|
||||
std::istringstream(used_for_object) >> std::boolalpha >> filament_info.used_for_object;
|
||||
std::istringstream(used_for_support) >> std::boolalpha >> filament_info.used_for_support;
|
||||
filament_info.group_id = parse_int_list(group_id);
|
||||
filament_info.nozzle_diameter = atof(nozzle_diameter.c_str());
|
||||
filament_info.nozzle_volume_type = volume_type;
|
||||
m_curr_plater->slice_filaments_info.push_back(filament_info);
|
||||
}
|
||||
return true;
|
||||
@@ -5756,6 +5904,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const ObjectToObjectDataMap &objects_data, const DynamicPrintConfig& config, int export_plate_idx = -1, bool save_gcode = true, bool use_loaded_id = false);
|
||||
bool _add_cut_information_file_to_archive(mz_zip_archive &archive, Model &model);
|
||||
bool _add_slice_info_config_file_to_archive(mz_zip_archive &archive, const Model &model, PlateDataPtrs &plate_data_list, const ObjectToObjectDataMap &objects_data, const DynamicPrintConfig& config);
|
||||
bool _add_filament_sequence_file_to_archive(mz_zip_archive& archive, const 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);
|
||||
bool _add_auxiliary_dir_to_archive(mz_zip_archive &archive, const std::string &aux_dir, PackingTemporaryData &data);
|
||||
@@ -6294,6 +6443,11 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_add_filament_sequence_file_to_archive(archive, plate_data_list)) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", _add_filament_sequence_file_to_archive failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
//BBS progress point
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(", before add auxiliary dir to 3mf\n");
|
||||
if (proFn) {
|
||||
@@ -7950,6 +8104,39 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Exporter::_add_filament_sequence_file_to_archive(mz_zip_archive& archive, const PlateDataPtrs& plate_data_list)
|
||||
{
|
||||
nlohmann::json sequence_json;
|
||||
|
||||
for (size_t idx = 0; idx < plate_data_list.size(); ++idx) {
|
||||
const PlateData* plate_data = plate_data_list[idx];
|
||||
if (!plate_data)
|
||||
continue;
|
||||
|
||||
std::vector<unsigned int> filament_sequence = plate_data->filament_change_sequence;
|
||||
std::transform(filament_sequence.begin(), filament_sequence.end(), filament_sequence.begin(),
|
||||
[](unsigned int filament_id) { return filament_id + 1; });
|
||||
|
||||
const std::string plate_key = "plate_" + std::to_string(idx + 1);
|
||||
sequence_json[plate_key]["sequence"] = filament_sequence;
|
||||
sequence_json[plate_key]["nozzle_sequence"] = plate_data->nozzle_change_sequence;
|
||||
sequence_json[plate_key]["optimal_assignment"] = plate_data->optimal_assignment;
|
||||
}
|
||||
|
||||
if (sequence_json.empty())
|
||||
return true;
|
||||
|
||||
const std::string out = sequence_json.dump();
|
||||
if (!mz_zip_writer_add_mem(&archive, FILAMENT_SEQUENCE_FILE.c_str(), out.c_str(), out.size(), MZ_DEFAULT_COMPRESSION)) {
|
||||
add_error("Unable to add filament sequence file to archive");
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__
|
||||
<< boost::format(", store filament sequence to 3mf, length %1%, failed\n") % out.length();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Exporter::_add_slice_info_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const ObjectToObjectDataMap &objects_data, const DynamicPrintConfig& config)
|
||||
{
|
||||
std::stringstream stream;
|
||||
@@ -7987,6 +8174,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
|
||||
std::vector<int> extruder_types = config.option<ConfigOptionEnumsGeneric>("extruder_type")->values;
|
||||
std::vector<int> nozzle_volume_types = config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type")->values;
|
||||
auto* nozzle_volume_type_option = dynamic_cast<const ConfigOptionEnumsGeneric*>(config.option("nozzle_volume_type"));
|
||||
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << EXTRUDER_TYPE_ATTR << "\" " << VALUE_ATTR << "=\"";
|
||||
add_vector(stream, extruder_types);
|
||||
@@ -8010,6 +8198,11 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << OUTSIDE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha<< plate_data->toolpath_outside << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SUPPORT_USED_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha<< plate_data->is_support_used << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << LABEL_OBJECT_ENABLED_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha<< plate_data->is_label_object_enabled << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << ENABLE_FILAMENT_DYNAMIC_MAP_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << false << "\"/>\n";
|
||||
{
|
||||
bool has_filament_switcher = config.has("has_filament_switcher") ? config.opt_bool("has_filament_switcher") : false;
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << HAS_FILAMENT_SWITCHER_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << has_filament_switcher << "\"/>\n";
|
||||
}
|
||||
|
||||
std::vector<int> filament_maps = plate_data->filament_maps;
|
||||
if (filament_maps.empty())
|
||||
@@ -8053,20 +8246,69 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
<< "\" />\n";
|
||||
}
|
||||
|
||||
auto get_nozzle_group_id = [&filament_maps](int filament_id) {
|
||||
if (filament_id >= 0 && filament_id < static_cast<int>(filament_maps.size()) && filament_maps[filament_id] > 0)
|
||||
return filament_maps[filament_id] - 1;
|
||||
return 0;
|
||||
};
|
||||
auto get_nozzle_diameter = [nozzle_diameter_option](int nozzle_group_id) {
|
||||
if (!nozzle_diameter_option || nozzle_diameter_option->values.empty())
|
||||
return 0.0;
|
||||
if (nozzle_group_id >= 0 && nozzle_group_id < static_cast<int>(nozzle_diameter_option->values.size()))
|
||||
return nozzle_diameter_option->values[nozzle_group_id];
|
||||
return nozzle_diameter_option->values.front();
|
||||
};
|
||||
auto get_nozzle_diameter_str = [&get_nozzle_diameter](int nozzle_group_id) {
|
||||
std::ostringstream diameter_stream;
|
||||
diameter_stream << std::defaultfloat << get_nozzle_diameter(nozzle_group_id);
|
||||
return diameter_stream.str();
|
||||
};
|
||||
auto get_nozzle_volume_type = [nozzle_volume_type_option](int nozzle_group_id) {
|
||||
if (!nozzle_volume_type_option || nozzle_volume_type_option->values.empty())
|
||||
return std::string();
|
||||
int nozzle_volume_type = nozzle_volume_type_option->values.front();
|
||||
if (nozzle_group_id >= 0 && nozzle_group_id < static_cast<int>(nozzle_volume_type_option->values.size()))
|
||||
nozzle_volume_type = nozzle_volume_type_option->values[nozzle_group_id];
|
||||
if (nozzle_volume_type < 0 || nozzle_volume_type > nvtMaxNozzleVolumeType)
|
||||
nozzle_volume_type = nvtStandard;
|
||||
return get_nozzle_volume_type_string(static_cast<NozzleVolumeType>(nozzle_volume_type));
|
||||
};
|
||||
std::vector<int> used_nozzle_groups;
|
||||
|
||||
for (auto it = plate_data->slice_filaments_info.begin(); it != plate_data->slice_filaments_info.end(); it++)
|
||||
{
|
||||
int nozzle_group_id = get_nozzle_group_id(it->id);
|
||||
if (std::find(used_nozzle_groups.begin(), used_nozzle_groups.end(), nozzle_group_id) == used_nozzle_groups.end())
|
||||
used_nozzle_groups.push_back(nozzle_group_id);
|
||||
const std::string filament_nozzle_group_id = it->group_id.empty() ? std::to_string(nozzle_group_id) : join_int_list_comma(it->group_id);
|
||||
const double filament_nozzle_diameter = it->nozzle_diameter > 0.0 ? it->nozzle_diameter : get_nozzle_diameter(nozzle_group_id);
|
||||
const std::string filament_nozzle_volume_type = it->nozzle_volume_type.empty() ? get_nozzle_volume_type(nozzle_group_id) : it->nozzle_volume_type;
|
||||
|
||||
stream << " <" << FILAMENT_TAG << " " << FILAMENT_ID_TAG << "=\"" << std::to_string(it->id + 1) << "\" "
|
||||
<< FILAMENT_TRAY_INFO_ID_TAG <<"=\""<< it->filament_id <<"\" "
|
||||
<< FILAMENT_TYPE_TAG << "=\"" << it->type << "\" "
|
||||
<< FILAMENT_COLOR_TAG << "=\"" << it->color << "\" "
|
||||
<< FILAMENT_USED_M_TAG << "=\"" << it->used_m << "\" "
|
||||
<< FILAMENT_USED_G_TAG << "=\"" << it->used_g << "\" />\n";
|
||||
<< FILAMENT_USED_G_TAG << "=\"" << it->used_g << "\" "
|
||||
<< FILAMENT_NOZZLE_GROUP_ID_TAG << "=\"" << filament_nozzle_group_id << "\" "
|
||||
<< FILAMENT_NOZZLE_DIAMETER_TAG << "=\"" << filament_nozzle_diameter << "\" "
|
||||
<< FILAMENT_NOZZLE_VOLUME_TYPE_TAG << "=\"" << filament_nozzle_volume_type << "\" "
|
||||
<< FILAMENT_USED_FOR_OBJECT << "=\"" << std::boolalpha << it->used_for_object << "\" "
|
||||
<< FILAMENT_USED_FOR_SUPPORT << "=\"" << std::boolalpha << it->used_for_support << "\"/>\n";
|
||||
}
|
||||
|
||||
for (auto it = plate_data->warnings.begin(); it != plate_data->warnings.end(); it++) {
|
||||
stream << " <" << SLICE_WARNING_TAG << " msg=\"" << it->msg << "\" level=\"" << std::to_string(it->level) << "\" error_code =\"" << it->error_code << "\" />\n";
|
||||
}
|
||||
|
||||
for (int nozzle_group_id : used_nozzle_groups) {
|
||||
stream << " <" << NOZZLE_TAG << " "
|
||||
<< "id=\"" << nozzle_group_id << "\" "
|
||||
<< "extruder_id=\"" << nozzle_group_id + 1 << "\" "
|
||||
<< "nozzle_diameter=\"" << get_nozzle_diameter_str(nozzle_group_id) << "\" "
|
||||
<< "volume_type=\"" << get_nozzle_volume_type(nozzle_group_id) << "\"/>\n";
|
||||
}
|
||||
|
||||
if (!plate_data->layer_filaments.empty()) {
|
||||
stream << " <" << LAYER_FILAMENT_LISTS_TAG << ">\n";
|
||||
for (auto iter = plate_data->layer_filaments.begin(); iter != plate_data->layer_filaments.end(); ++iter) {
|
||||
|
||||
@@ -98,6 +98,9 @@ struct PlateData
|
||||
std::vector<int> filament_maps; // 1 base
|
||||
using LayerFilaments = std::unordered_map<std::vector<unsigned int>, std::vector<std::pair<int, int>>, GCodeProcessorResult::FilamentSequenceHash>;
|
||||
LayerFilaments layer_filaments;
|
||||
std::vector<unsigned int> filament_change_sequence;
|
||||
std::vector<unsigned int> nozzle_change_sequence;
|
||||
std::vector<int> optimal_assignment;
|
||||
|
||||
// Hexadecimal number,
|
||||
// the 0th digit corresponds to extruder 1
|
||||
|
||||
@@ -94,6 +94,16 @@ static const float g_purge_volume_one_time = 135.f;
|
||||
static const int g_max_flush_count = 4;
|
||||
static const size_t g_max_label_object = 64;
|
||||
|
||||
static bool is_bambu_x2d_printer(const FullPrintConfig &config)
|
||||
{
|
||||
return config.printer_model.value == "Bambu Lab X2D";
|
||||
}
|
||||
|
||||
static int hotend_id_for_gcode_placeholder(const FullPrintConfig &config, int hotend_id)
|
||||
{
|
||||
return is_bambu_x2d_printer(config) ? -1 : hotend_id;
|
||||
}
|
||||
|
||||
Vec2d travel_point_1;
|
||||
Vec2d travel_point_2;
|
||||
Vec2d travel_point_3;
|
||||
@@ -835,6 +845,10 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
|
||||
config.set_key_value("previous_extruder", new ConfigOptionInt(old_filament_id));
|
||||
config.set_key_value("next_extruder", new ConfigOptionInt(new_filament_id));
|
||||
config.set_key_value("current_hotend", new ConfigOptionInt(old_extruder_id >= 0 ?
|
||||
hotend_id_for_gcode_placeholder(gcodegen.m_config, old_extruder_id) : -1));
|
||||
config.set_key_value("next_hotend",
|
||||
new ConfigOptionInt(hotend_id_for_gcode_placeholder(gcodegen.m_config, (int) gcodegen.get_extruder_id(new_filament_id))));
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(gcodegen.m_layer_index));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(tcr.print_z));
|
||||
config.set_key_value("toolchange_z", new ConfigOptionFloat(z));
|
||||
@@ -916,6 +930,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
|
||||
auto flush_v_speed = m_print_config->filament_flush_volumetric_speed.values;
|
||||
auto flush_temps = m_print_config->filament_flush_temp.values;
|
||||
auto filament_cooling_before_tower = m_print_config->filament_cooling_before_tower.values;
|
||||
for (size_t idx = 0; idx < flush_v_speed.size(); ++idx) {
|
||||
if (flush_v_speed[idx] == 0)
|
||||
flush_v_speed[idx] = m_print_config->filament_max_volumetric_speed.get_at(idx);
|
||||
@@ -924,8 +939,13 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
if (flush_temps[idx] == 0)
|
||||
flush_temps[idx] = m_print_config->nozzle_temperature_range_high.get_at(idx);
|
||||
}
|
||||
if (filament_cooling_before_tower.size() < m_print_config->filament_type.values.size())
|
||||
filament_cooling_before_tower.resize(m_print_config->filament_type.values.size(), m_print_config->filament_cooling_before_tower.get_at(0));
|
||||
if (tcr.is_contact || gcodegen.m_layer_index == 0)
|
||||
std::fill(filament_cooling_before_tower.begin(), filament_cooling_before_tower.end(), 0);
|
||||
config.set_key_value("flush_volumetric_speeds", new ConfigOptionFloats(flush_v_speed));
|
||||
config.set_key_value("flush_temperatures", new ConfigOptionInts(flush_temps));
|
||||
config.set_key_value("filament_cooling_before_tower", new ConfigOptionFloats(filament_cooling_before_tower));
|
||||
config.set_key_value("flush_length", new ConfigOptionFloat(purge_length));
|
||||
config.set_key_value("wipe_avoid_perimeter", new ConfigOptionBool(is_used_travel_avoid_perimeter));
|
||||
config.set_key_value("wipe_avoid_pos_x", new ConfigOptionFloat(wipe_avoid_pos_x));
|
||||
@@ -2791,7 +2811,10 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
this->placeholder_parser().set("first_non_support_filaments", new ConfigOptionInts(first_non_support_filaments));
|
||||
this->placeholder_parser().set("initial_no_support_tool", initial_non_support_extruder_id);
|
||||
this->placeholder_parser().set("initial_no_support_extruder", initial_non_support_extruder_id);
|
||||
this->placeholder_parser().set("initial_no_support_hotend",
|
||||
hotend_id_for_gcode_placeholder(m_config, (int) get_extruder_id(initial_non_support_extruder_id)));
|
||||
this->placeholder_parser().set("current_extruder", initial_extruder_id);
|
||||
this->placeholder_parser().set("current_hotend", hotend_id_for_gcode_placeholder(m_config, extruder_id));
|
||||
//Orca: set the key for compatibilty
|
||||
this->placeholder_parser().set("retraction_distance_when_cut", m_config.retraction_distances_when_cut.get_at(initial_extruder_id));
|
||||
this->placeholder_parser().set("long_retraction_when_cut", m_config.long_retractions_when_cut.get_at(initial_extruder_id));
|
||||
@@ -2806,7 +2829,9 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
this->placeholder_parser().set("long_retractions_when_ec",new ConfigOptionBoolsNullable(m_config.long_retractions_when_ec));
|
||||
|
||||
this->placeholder_parser().set("max_additional_fan", max_additional_fan);
|
||||
this->placeholder_parser().set("first_x_layer_fan_speed", 0); // TODO: Orca hack to support BBL profiles
|
||||
this->placeholder_parser().set("first_x_layer_fan_speed", new ConfigOptionFloats(m_config.first_x_layer_fan_speed));
|
||||
this->placeholder_parser().set("close_additional_fan_first_x_layers", new ConfigOptionInts(m_config.close_additional_fan_first_x_layers));
|
||||
this->placeholder_parser().set("additional_fan_full_speed_layer", new ConfigOptionInts(m_config.additional_fan_full_speed_layer));
|
||||
|
||||
auto flush_v_speed = m_config.filament_flush_volumetric_speed.values;
|
||||
auto flush_temps = m_config.filament_flush_temp.values;
|
||||
@@ -2820,6 +2845,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
}
|
||||
this->placeholder_parser().set("flush_volumetric_speeds", new ConfigOptionFloats(flush_v_speed));
|
||||
this->placeholder_parser().set("flush_temperatures", new ConfigOptionInts(flush_temps));
|
||||
this->placeholder_parser().set("filament_cooling_before_tower", new ConfigOptionFloatsNullable(m_config.filament_cooling_before_tower));
|
||||
//Set variable for total layer count so it can be used in custom gcode.
|
||||
this->placeholder_parser().set("total_layer_count", m_layer_count);
|
||||
// Useful for sequential prints.
|
||||
@@ -3520,6 +3546,30 @@ void GCode::export_layer_filaments(GCodeProcessorResult* result)
|
||||
iter->second.emplace_back(idx, idx);
|
||||
}
|
||||
}
|
||||
|
||||
result->filament_change_sequence.clear();
|
||||
result->nozzle_change_sequence.clear();
|
||||
|
||||
int prev_sequence_filament = -1;
|
||||
int prev_sequence_nozzle = -1;
|
||||
for (size_t layer_idx = 0; layer_idx < m_sorted_layer_filaments.size(); ++layer_idx) {
|
||||
for (unsigned int filament_id : m_sorted_layer_filaments[layer_idx]) {
|
||||
int nozzle_id = 0;
|
||||
if (filament_id < filament_map.size() && filament_map[filament_id] > 0)
|
||||
nozzle_id = filament_map[filament_id] - 1;
|
||||
if (prev_sequence_nozzle != nozzle_id || prev_sequence_filament != static_cast<int>(filament_id)) {
|
||||
result->nozzle_change_sequence.emplace_back(static_cast<unsigned int>(nozzle_id));
|
||||
result->filament_change_sequence.emplace_back(filament_id);
|
||||
prev_sequence_nozzle = nozzle_id;
|
||||
prev_sequence_filament = static_cast<int>(filament_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result->optimal_assignment.clear();
|
||||
result->optimal_assignment.reserve(filament_map.size());
|
||||
for (int nozzle_id : filament_map)
|
||||
result->optimal_assignment.emplace_back(nozzle_id > 0 ? nozzle_id - 1 : 0);
|
||||
}
|
||||
|
||||
//BBS
|
||||
@@ -6320,7 +6370,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
}
|
||||
|
||||
// calculate effective extrusion length per distance unit (e_per_mm)
|
||||
double filament_flow_ratio = m_config.option<ConfigOptionFloats>("filament_flow_ratio")->get_at(0);
|
||||
double filament_flow_ratio = FILAMENT_CONFIG(filament_flow_ratio);
|
||||
// We set _mm3_per_mm to effectove flow = Geometric volume * print flow ratio * filament flow ratio * role-based-flow-ratios
|
||||
auto _mm3_per_mm = path.mm3_per_mm * this->config().print_flow_ratio;
|
||||
_mm3_per_mm *= filament_flow_ratio;
|
||||
@@ -6516,7 +6566,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
if (ref_speed == 0)
|
||||
ref_speed = FILAMENT_CONFIG(filament_max_volumetric_speed) / _mm3_per_mm;
|
||||
|
||||
if (EXTRUDER_CONFIG(filament_max_volumetric_speed) > 0) {
|
||||
if (FILAMENT_CONFIG(filament_max_volumetric_speed) > 0) {
|
||||
ref_speed = std::min(ref_speed, FILAMENT_CONFIG(filament_max_volumetric_speed) / _mm3_per_mm);
|
||||
}
|
||||
if (sloped) {
|
||||
@@ -7660,6 +7710,7 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
float filament_area = float((M_PI / 4.f) * pow(m_config.filament_diameter.get_at(new_filament_id), 2));
|
||||
//BBS: add handling for filament change in start gcode
|
||||
int old_filament_id = -1;
|
||||
int old_extruder_id = -1;
|
||||
if (m_writer.filament() != nullptr || m_start_gcode_filament != -1) {
|
||||
std::vector<float> flush_matrix(cast<float>(get_flush_volumes_matrix(m_config.flush_volumes_matrix.values, new_extruder_id, m_config.nozzle_diameter.values.size())));
|
||||
const unsigned int number_of_extruders = (unsigned int) (m_config.filament_colour.values.size()); // if is multi_extruder only use the fist extruder matrix
|
||||
@@ -7669,7 +7720,7 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
assert(m_start_gcode_filament < number_of_extruders);
|
||||
|
||||
old_filament_id = m_writer.filament() != nullptr ? m_writer.filament()->id() : m_start_gcode_filament;
|
||||
int old_extruder_id = m_writer.filament() != nullptr ? m_writer.filament()->extruder_id() : get_extruder_id(m_start_gcode_filament);
|
||||
old_extruder_id = m_writer.filament() != nullptr ? m_writer.filament()->extruder_id() : get_extruder_id(m_start_gcode_filament);
|
||||
|
||||
old_retract_length = m_config.retraction_length.get_at(old_filament_id);
|
||||
old_retract_length_toolchange = m_config.retract_length_toolchange.get_at(old_filament_id);
|
||||
@@ -7715,6 +7766,9 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
dyn_config.set_key_value("outer_wall_volumetric_speed", new ConfigOptionFloat(outer_wall_volumetric_speed));
|
||||
dyn_config.set_key_value("previous_extruder", new ConfigOptionInt(old_filament_id));
|
||||
dyn_config.set_key_value("next_extruder", new ConfigOptionInt((int)new_filament_id));
|
||||
dyn_config.set_key_value("current_hotend",
|
||||
new ConfigOptionInt(old_filament_id >= 0 ? hotend_id_for_gcode_placeholder(m_config, old_extruder_id) : -1));
|
||||
dyn_config.set_key_value("next_hotend", new ConfigOptionInt(hotend_id_for_gcode_placeholder(m_config, new_extruder_id)));
|
||||
dyn_config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
dyn_config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
dyn_config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
@@ -7767,7 +7821,8 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
}
|
||||
|
||||
auto flush_v_speed = m_print->config().filament_flush_volumetric_speed.values;
|
||||
auto flush_temps =m_print->config().filament_flush_temp.values;
|
||||
auto flush_temps = m_print->config().filament_flush_temp.values;
|
||||
auto filament_cooling_before_tower = m_print->config().filament_cooling_before_tower.values;
|
||||
for (size_t idx = 0; idx < flush_v_speed.size(); ++idx) {
|
||||
if (flush_v_speed[idx] == 0)
|
||||
flush_v_speed[idx] = m_print->config().filament_max_volumetric_speed.get_at(idx);
|
||||
@@ -7776,8 +7831,12 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
if (flush_temps[idx] == 0)
|
||||
flush_temps[idx] = m_print->config().nozzle_temperature_range_high.get_at(idx);
|
||||
}
|
||||
if (filament_cooling_before_tower.size() < m_print->config().filament_type.values.size())
|
||||
filament_cooling_before_tower.resize(m_print->config().filament_type.values.size(), m_print->config().filament_cooling_before_tower.get_at(0));
|
||||
std::fill(filament_cooling_before_tower.begin(), filament_cooling_before_tower.end(), 0);
|
||||
dyn_config.set_key_value("flush_volumetric_speeds", new ConfigOptionFloats(flush_v_speed));
|
||||
dyn_config.set_key_value("flush_temperatures", new ConfigOptionInts(flush_temps));
|
||||
dyn_config.set_key_value("filament_cooling_before_tower", new ConfigOptionFloats(filament_cooling_before_tower));
|
||||
dyn_config.set_key_value("flush_length", new ConfigOptionFloat(wipe_length));
|
||||
|
||||
int flush_count = std::min(g_max_flush_count, (int)std::round(wipe_volume / g_purge_volume_one_time));
|
||||
@@ -7850,6 +7909,7 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
}
|
||||
|
||||
this->placeholder_parser().set("current_extruder", new_filament_id);
|
||||
this->placeholder_parser().set("current_hotend", hotend_id_for_gcode_placeholder(m_config, new_extruder_id));
|
||||
this->placeholder_parser().set("retraction_distance_when_cut", m_config.retraction_distances_when_cut.get_at(new_filament_id));
|
||||
this->placeholder_parser().set("long_retraction_when_cut", m_config.long_retractions_when_cut.get_at(new_filament_id));
|
||||
this->placeholder_parser().set("retraction_distance_when_ec", m_config.retraction_distances_when_ec.get_at(new_filament_id));
|
||||
|
||||
@@ -1582,6 +1582,9 @@ void GCodeProcessorResult::reset() {
|
||||
custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
|
||||
spiral_vase_mode = false;
|
||||
layer_filaments.clear();
|
||||
filament_change_sequence.clear();
|
||||
nozzle_change_sequence.clear();
|
||||
optimal_assignment.clear();
|
||||
filament_change_count_map.clear();
|
||||
warnings.clear();
|
||||
|
||||
|
||||
@@ -251,6 +251,9 @@ class Print;
|
||||
std::vector<NozzleType> nozzle_type;
|
||||
// first key stores filaments, second keys stores the layer ranges(enclosed) that use the filaments
|
||||
std::unordered_map<std::vector<unsigned int>, std::vector<std::pair<int, int>>,FilamentSequenceHash> layer_filaments;
|
||||
std::vector<unsigned int> nozzle_change_sequence;
|
||||
std::vector<unsigned int> filament_change_sequence;
|
||||
std::vector<int> optimal_assignment;
|
||||
// first key stores `from` filament, second keys stores the `to` filament
|
||||
std::map<std::pair<int,int>, int > filament_change_count_map;
|
||||
|
||||
@@ -288,6 +291,9 @@ class Print;
|
||||
limit_filament_maps = other.limit_filament_maps;
|
||||
filament_printable_reuslt = other.filament_printable_reuslt;
|
||||
layer_filaments = other.layer_filaments;
|
||||
filament_change_sequence = other.filament_change_sequence;
|
||||
nozzle_change_sequence = other.nozzle_change_sequence;
|
||||
optimal_assignment = other.optimal_assignment;
|
||||
filament_change_count_map = other.filament_change_count_map;
|
||||
initial_layer_time = other.initial_layer_time;
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
||||
@@ -1281,7 +1281,7 @@ static std::vector<std::string> s_Preset_filament_options {/*"filament_colour",
|
||||
// "bed_type",
|
||||
//BBS:temperature_vitrification
|
||||
"temperature_vitrification", "reduce_fan_stop_start_freq","dont_slow_down_outer_wall", "slow_down_for_layer_cooling", "fan_min_speed",
|
||||
"fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "overhang_fan_threshold", "close_fan_the_first_x_layers", "full_fan_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed",
|
||||
"fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "overhang_fan_threshold", "close_fan_the_first_x_layers", "close_additional_fan_first_x_layers", "first_x_layer_fan_speed", "full_fan_speed_layer", "additional_fan_full_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed",
|
||||
"filament_start_gcode", "filament_end_gcode", "filament_change_extrusion_role_gcode",
|
||||
//exhaust fan control
|
||||
"activate_air_filtration","activate_air_filtration_during_print","activate_air_filtration_on_completion","during_print_exhaust_fan_speed","complete_print_exhaust_fan_speed",
|
||||
@@ -1305,7 +1305,7 @@ static std::vector<std::string> s_Preset_filament_options {/*"filament_colour",
|
||||
"filament_multitool_ramming", "filament_multitool_ramming_volume", "filament_multitool_ramming_flow", "activate_chamber_temp_control",
|
||||
"filament_long_retractions_when_cut","filament_retraction_distances_when_cut", "idle_temperature",
|
||||
//BBS filament change length while the extruder color
|
||||
"filament_change_length","filament_flush_volumetric_speed","filament_flush_temp",
|
||||
"filament_change_length","filament_flush_volumetric_speed","filament_flush_temp", "filament_cooling_before_tower",
|
||||
"long_retractions_when_ec", "retraction_distances_when_ec"
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
@@ -446,7 +447,7 @@ CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(OverhangFanThreshold)
|
||||
// BBS
|
||||
static const t_config_enum_values s_keys_map_BedType = {
|
||||
{ "Default Plate", btDefault },
|
||||
{ "SuperTack Plate", btSuperTack },
|
||||
{ "Supertack Plate", btSuperTack },
|
||||
{ "Cool Plate", btPC },
|
||||
{ "Engineering Plate", btEP },
|
||||
{ "High Temp Plate", btPEI },
|
||||
@@ -1014,7 +1015,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->enum_values.emplace_back("High Temp Plate");
|
||||
def->enum_values.emplace_back("Textured PEI Plate");
|
||||
def->enum_values.emplace_back("Textured Cool Plate");
|
||||
def->enum_values.emplace_back("SuperTack Plate");
|
||||
def->enum_values.emplace_back("Supertack Plate");
|
||||
def->enum_labels.emplace_back(L("Smooth Cool Plate"));
|
||||
def->enum_labels.emplace_back(L("Engineering Plate"));
|
||||
def->enum_labels.emplace_back(L("Smooth High Temp Plate"));
|
||||
@@ -2637,6 +2638,14 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 15. });
|
||||
|
||||
def = this->add("filament_cooling_before_tower", coFloats);
|
||||
def->label = L("Wipe tower cooling");
|
||||
def->tooltip = L("Temperature drop before entering filament tower");
|
||||
def->sidetext = L(u8"\u2103" /* °C */); // degrees Celsius, CIS languages need translation
|
||||
def->mode = comDevelop;
|
||||
def->nullable = true;
|
||||
def->set_default_value(new ConfigOptionFloatsNullable { 10. });
|
||||
|
||||
def = this->add("filament_tower_interface_pre_extrusion_dist", coFloats);
|
||||
def->label = L("Interface layer pre-extrusion distance");
|
||||
def->tooltip = L("Pre-extrusion distance for prime tower interface layer (where different materials meet).");
|
||||
@@ -4524,6 +4533,33 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionInts { 0 });
|
||||
|
||||
def = this->add("close_additional_fan_first_x_layers", coInts);
|
||||
def->label = L("For the first");
|
||||
def->tooltip = L("Set special auxiliary cooling fan for the first certain layers.");
|
||||
def->sidetext = L("layers");
|
||||
def->min = 0;
|
||||
def->max = 1000;
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionInts { 1 });
|
||||
|
||||
def = this->add("additional_fan_full_speed_layer", coInts);
|
||||
def->label = L("Full fan speed at layer");
|
||||
def->tooltip = L("Auxiliary fan speed will be ramped up linearly from layer \"For the first\" to maximum at layer \"Full fan speed at layer\". "
|
||||
"\"Full fan speed at layer\" will be ignored if lower than \"For the first\", in which case the fan will run at maximum allowed speed at layer \"For the first\" + 1.");
|
||||
def->min = 0;
|
||||
def->max = 1000;
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionInts { 0 });
|
||||
|
||||
def = this->add("first_x_layer_fan_speed", coFloats);
|
||||
def->label = L("Fan speed");
|
||||
def->tooltip = L("Special auxiliary cooling fan speed, effective only for the first x layers.");
|
||||
def->sidetext = "%";
|
||||
def->min = 0;
|
||||
def->max = 100;
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionFloats { 0 });
|
||||
|
||||
def = this->add("min_layer_height", coFloats);
|
||||
def->label = L("Min");
|
||||
def->tooltip = L("The lowest printable layer height for the extruder. "
|
||||
@@ -7680,7 +7716,9 @@ void PrintConfigDef::init_sla_params()
|
||||
void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value)
|
||||
{
|
||||
//BBS: handle legacy options
|
||||
if (opt_key == "enable_wipe_tower") {
|
||||
if (opt_key == "curr_bed_type" && value == "SuperTack Plate") {
|
||||
value = "Supertack Plate";
|
||||
} else if (opt_key == "enable_wipe_tower") {
|
||||
opt_key = "enable_prime_tower";
|
||||
} else if (opt_key == "wipe_tower_width") {
|
||||
opt_key = "prime_tower_width";
|
||||
@@ -8023,6 +8061,7 @@ std::set<std::string> filament_options_with_variant = {
|
||||
"nozzle_temperature",
|
||||
"filament_flush_volumetric_speed",
|
||||
"filament_flush_temp",
|
||||
"filament_cooling_before_tower",
|
||||
"volumetric_speed_coefficients",
|
||||
"filament_adaptive_volumetric_speed",
|
||||
"filament_ironing_flow",
|
||||
@@ -8581,16 +8620,37 @@ int DynamicPrintConfig::get_index_for_extruder(int extruder_or_filament_id, std:
|
||||
|
||||
auto variant_opt = dynamic_cast<const ConfigOptionStrings*>(this->option(variant_name));
|
||||
const ConfigOptionInts* id_opt = id_name.empty()?nullptr: dynamic_cast<const ConfigOptionInts*>(this->option(id_name));
|
||||
const ConfigOptionStrings* extruder_variant_list_opt = dynamic_cast<const ConfigOptionStrings*>(this->option("extruder_variant_list"));
|
||||
auto generated_extruder_id = [extruder_variant_list_opt](int target_index) {
|
||||
if (!extruder_variant_list_opt)
|
||||
return 0;
|
||||
|
||||
int variant_index = 0;
|
||||
for (int extruder_index = 0; extruder_index < int(extruder_variant_list_opt->values.size()); ++extruder_index) {
|
||||
std::vector<std::string> variants_list;
|
||||
boost::split(variants_list, extruder_variant_list_opt->get_at(extruder_index), boost::is_any_of(","), boost::token_compress_on);
|
||||
for (std::string variant : variants_list) {
|
||||
boost::trim(variant);
|
||||
if (variant.empty())
|
||||
continue;
|
||||
if (variant_index == target_index)
|
||||
return extruder_index + 1;
|
||||
++variant_index;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
if (variant_opt != nullptr) {
|
||||
int v_size = variant_opt->values.size();
|
||||
//int i_size = id_opt->values.size();
|
||||
const bool has_complete_id_map = id_opt && int(id_opt->values.size()) >= v_size;
|
||||
std::string extruder_variant = get_extruder_variant_string(extruder_type, nozzle_volume_type);
|
||||
for (int index = 0; index < v_size; index++)
|
||||
{
|
||||
const std::string variant = variant_opt->get_at(index);
|
||||
if (extruder_variant == variant) {
|
||||
if (id_opt) {
|
||||
const int id = id_opt->get_at(index);
|
||||
const int id = has_complete_id_map ? id_opt->get_at(index) : generated_extruder_id(index);
|
||||
if (id == extruder_or_filament_id) {
|
||||
ret = index * stride;
|
||||
break;
|
||||
|
||||
@@ -1400,6 +1400,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionInts, filament_cooling_moves))
|
||||
((ConfigOptionFloats, filament_cooling_initial_speed))
|
||||
((ConfigOptionFloats, filament_minimal_purge_on_wipe_tower))
|
||||
((ConfigOptionFloatsNullable, filament_cooling_before_tower))
|
||||
((ConfigOptionFloats, filament_tower_interface_pre_extrusion_dist))
|
||||
((ConfigOptionFloats, filament_tower_interface_pre_extrusion_length))
|
||||
((ConfigOptionFloats, filament_tower_ironing_area))
|
||||
@@ -1430,6 +1431,9 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
||||
|
||||
//BBS
|
||||
((ConfigOptionInts, additional_cooling_fan_speed))
|
||||
((ConfigOptionInts, close_additional_fan_first_x_layers))
|
||||
((ConfigOptionInts, additional_fan_full_speed_layer))
|
||||
((ConfigOptionFloats, first_x_layer_fan_speed))
|
||||
((ConfigOptionBool, reduce_crossing_wall))
|
||||
((ConfigOptionFloatOrPercent, max_travel_detour_distance))
|
||||
((ConfigOptionPoints, printable_area))
|
||||
|
||||
@@ -49,6 +49,11 @@ struct FilamentInfo
|
||||
int ctype = 0;
|
||||
std::vector<std::string> colors = std::vector<std::string>();
|
||||
int mapping_result = 0;
|
||||
bool used_for_support{false};
|
||||
bool used_for_object{false};
|
||||
std::vector<int> group_id;
|
||||
double nozzle_diameter{0.0};
|
||||
std::string nozzle_volume_type;
|
||||
|
||||
/*for new ams mapping*/
|
||||
std::string ams_id;
|
||||
|
||||
Reference in New Issue
Block a user