mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-14 03:11:19 +00:00
Merge upstream main: color mixing feature and related fixes
Brings in 54 upstream commits, the bulk of them the BambuStudio-ported color mixing / mixed filament subsystem (#15347) plus its follow-ups, along with the Assimp-backed colored OBJ import, warning-policy build changes, and assorted profile and localization updates. Two conflicts, both "each side added at the same point", resolved by keeping both: - Print::validate() -- our IMEX multi-color block and upstream's new gradient mixed filament warning were inserted at the same spot after the empty extruders check. They test unrelated conditions, so both are kept, each with its own closing brace. - tests/libslic3r/test_3mf.cpp -- our three IMEX per-plate round-trip scenarios and upstream's mixed-filament round-trip scenario both append to the end of the file, and each side added one include. All four scenarios and both includes are kept. Everything else merged cleanly, including GCode.cpp, ToolOrdering.cpp, PartPlate.cpp and PrintConfig.cpp. Upstream left the is_extruder_used block untouched, so the IMEX supplement still applies, and estimate_wipe_tower_polygon is unchanged, so the prime tower hull work is unaffected. Not addressed here, and worth its own change: a mixed filament is a virtual slot that no nozzle carries, while physical_extruder_map routes logical slots to physical heads. Print::extruders() lists mixed slots under their own id whereas tool_ordering.all_extruders() lists them post-expansion, so the IMEX pem lookups have no defined answer for a mixed slot. Upstream's own guards reject a mixed filament where a physical slot is required; IMEX likely wants the same. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include "PrintConfigConstants.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "FilamentMixer.hpp"
|
||||
#include "MaterialType.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "format.hpp"
|
||||
@@ -3282,6 +3283,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
|
||||
@@ -7549,6 +7606,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.");
|
||||
@@ -9752,7 +9817,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");
|
||||
@@ -11900,6 +11973,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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user