Merge remote-tracking branch 'upstream/main' into haryr/aug25-rebase

# Conflicts:
#	src/libslic3r/GCode/ToolOrdering.cpp
#	src/libslic3r/Print.cpp
#	src/libslic3r/PrintApply.cpp
#	src/libslic3r/PrintConfig.cpp
#	src/slic3r/GUI/Tab.cpp
This commit is contained in:
harrierpigeon
2026-08-30 23:30:51 -05:00
110 changed files with 38067 additions and 306 deletions
+91 -1
View File
@@ -4,6 +4,7 @@
#include "ClipperUtils.hpp"
#include "Config.hpp"
#include "Geometry.hpp"
#include "FilamentMixer.hpp"
#include "MaterialType.hpp"
#include "I18N.hpp"
#include "format.hpp"
@@ -3355,6 +3356,62 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBools { false });
// Mixed-color filament. A slot flagged here is virtual: it is not loaded into any
// physical extruder, but resolved at slicing time into the physical filaments listed
// in filament_mixed_components, blended either by splitting each layer into
// sub-layers or by alternating whole layers (see enable_mixed_color_sublayer).
def = this->add("filament_is_mixed", coBools);
def->label = L("Is mixed filament");
def->tooltip = L("Whether this filament slot is a mixed filament composed of multiple physical filaments");
def->mode = comDevelop;
def->set_default_value(new ConfigOptionBools{false});
def = this->add("filament_mixed_components", coStrings);
def->label = L("Mixed filament components");
def->tooltip = L("Comma-separated 1-based indices of component filaments, e.g. \"1,3\"");
def->mode = comDevelop;
def->set_default_value(new ConfigOptionStrings{""});
def = this->add("filament_mixed_sublayer_ratios", coStrings);
def->label = L("Mixed filament sublayer ratios");
def->tooltip = L("Comma-separated ratio values summing to 1.0, e.g. \"0.7,0.3\"");
def->mode = comDevelop;
def->set_default_value(new ConfigOptionStrings{""});
def = this->add("filament_mixed_gradient", coBools);
def->label = L("Mixed filament gradient");
def->tooltip = L("Enable Z-direction gradient mode for mixed filament sub-layers. "
"When enabled, the sub-layer ratios vary linearly across layers.");
def->mode = comDevelop;
def->set_default_value(new ConfigOptionBools{false});
def = this->add("filament_mixed_gradient_range", coStrings);
def->label = L("Mixed filament gradient range");
def->tooltip = L("Start and end ratios for the first component in gradient mode. "
"Comma-separated pair, e.g. \"0.10,0.90\" means 10% to 90%.");
def->mode = comDevelop;
def->set_default_value(new ConfigOptionStrings{""});
def = this->add("filament_mixed_gradient_curve", coStrings);
def->label = L("Mixed filament gradient curve");
def->tooltip = L("Optional Photoshop-style custom curve mapping Z progress to the first "
"component ratio. Encoded as pipe-separated control points, "
"either \"x,y\" (legacy) or \"x,y,m_in,m_out\" when a tangent override "
"is needed (empty token or \"nan\" means use PCHIP default). "
"x in [0,1]; y is clamped to the configured ratio range, "
"e.g. \"0,0.15|0.5,0.50|1,0.85\". When empty, the linear "
"gradient_range is used instead.");
def->mode = comDevelop;
def->set_default_value(new ConfigOptionStrings{""});
def = this->add("filament_mixed_gradient_per_part", coBools);
def->label = L("Mixed filament per-part gradient");
def->tooltip = L("When gradient mode is enabled, apply the gradient to each part of an "
"assembly independently rather than treating the whole assembly as one "
"Z range.");
def->mode = comDevelop;
def->set_default_value(new ConfigOptionBools{false});
// defined in bits
// 0 means cannot support, 1 means support
// 0 bit: can support in left extruder
@@ -7785,6 +7842,14 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloats { 1. });
def = this->add("enable_mixed_color_sublayer", coBool);
def->label = L("Mixed color sublayer");
def->tooltip = L("Enable mixed color sublayer splitting. When enabled, layers containing mixed color "
"filaments will be split into sub-layers to achieve color mixing effects.");
def->category = L("Quality");
def->mode = comSimple;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("enable_prime_tower", coBool);
def->label = L("Enable");
def->tooltip = L("The wiping tower can be used to clean up residue on the nozzle and stabilize the chamber pressure inside the nozzle in order to avoid appearance defects when printing objects.");
@@ -9998,7 +10063,15 @@ t_config_option_keys DynamicPrintConfig::normalize_fdm_2(int num_objects, int us
ConfigOptionBool *enable_wrapping_opt = this->option<ConfigOptionBool>("enable_wrapping_detection");
bool enable_wrapping = enable_wrapping_opt != nullptr && enable_wrapping_opt->value;
if (!is_smooth_timelapse && !enable_wrapping && (used_filaments == 1 || (ps_opt->value == PrintSequence::ByObject && num_objects > 1))) {
bool has_mixed_filament = false;
{
auto *mixed_opt = this->option<ConfigOptionBools>("filament_is_mixed");
if (mixed_opt)
has_mixed_filament = has_any_mixed_filament(mixed_opt->values);
}
if (!is_smooth_timelapse && !enable_wrapping
&& ( (used_filaments == 1 && !has_mixed_filament)
|| (ps_opt->value == PrintSequence::ByObject && num_objects > 1))) {
if (ept_opt->value) {
ept_opt->value = false;
changed_keys.push_back("enable_prime_tower");
@@ -12146,6 +12219,23 @@ std::map<std::string, std::string> validate(const FullPrintConfig &cfg, bool und
}
}
// Mixed-color (混色) parameter validation.
{
const auto &is_mixed = cfg.filament_is_mixed.values;
const auto &comp_strs = cfg.filament_mixed_components.values;
const auto &ratio_strs = cfg.filament_mixed_sublayer_ratios.values;
const auto &gradient_flags = cfg.filament_mixed_gradient.values;
const auto &range_strs = cfg.filament_mixed_gradient_range.values;
const auto &curve_strs = cfg.filament_mixed_gradient_curve.values;
std::map<std::string, std::string> mixed_errors = validate_mixed_filament_params(
is_mixed, comp_strs, ratio_strs, gradient_flags,
range_strs, curve_strs);
for (const auto &kv : mixed_errors)
if (error_message.find(kv.first) == error_message.end())
error_message.emplace(kv.first, kv.second);
}
// The configuration is valid.
return error_message;
}