mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-22 10:22:08 +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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user