mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-07 15:51:08 +00:00
Give each extruder its own machine limits
This commit is contained in:
@@ -10032,6 +10032,48 @@ static void extend_extruder_variant(DynamicPrintConfig& config, const unsigned i
|
||||
}
|
||||
}
|
||||
|
||||
// Options in printer_options_with_variant_2 are stored as (normal,silent) pairs per printer variant.
|
||||
// Some legacy presets/projects carry a variant list but still store only one pair; normalize to avoid crashes.
|
||||
static void normalize_stride2_floats(ConfigOptionFloats &opt, size_t expected_size)
|
||||
{
|
||||
auto &v = opt.values;
|
||||
if (expected_size == 0) {
|
||||
v.clear();
|
||||
return;
|
||||
}
|
||||
if (v.empty()) {
|
||||
// Fallback: keep behavior predictable instead of crashing. This should be rare.
|
||||
v.resize(expected_size, 0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
const double first = v[0];
|
||||
const double second = (v.size() >= 2) ? v[1] : first;
|
||||
|
||||
// Ensure we have at least one (normal,silent) pair to replicate.
|
||||
if (v.size() < 2) {
|
||||
v.resize(2, first);
|
||||
v[1] = second;
|
||||
}
|
||||
// Keep pair alignment if some legacy preset produced odd length.
|
||||
if (v.size() % 2 != 0)
|
||||
v.push_back(second);
|
||||
|
||||
if (v.size() > expected_size) {
|
||||
v.resize(expected_size);
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t have_variants = v.size() / 2;
|
||||
const size_t want_variants = expected_size / 2;
|
||||
v.resize(expected_size);
|
||||
for (size_t vi = have_variants; vi < want_variants; ++vi) {
|
||||
v[vi * 2] = first;
|
||||
if (vi * 2 + 1 < v.size())
|
||||
v[vi * 2 + 1] = second;
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicPrintConfig::set_num_extruders(unsigned int num_extruders)
|
||||
{
|
||||
extend_extruder_variant(*this, num_extruders);
|
||||
@@ -10049,6 +10091,11 @@ void DynamicPrintConfig::set_num_extruders(unsigned int num_extruders)
|
||||
static_cast<ConfigOptionVectorBase*>(opt)->resize(get_parameter_size(key, num_extruders), defaults.option(key));
|
||||
}
|
||||
}
|
||||
// Orca: machine limits are not extruder option keys and need a pair-aware resize, so that every
|
||||
// printer variant has its own (normal, silent) pair to edit.
|
||||
for (const std::string &key : printer_options_with_variant_2)
|
||||
if (auto *opt = this->option<ConfigOptionFloats>(key))
|
||||
normalize_stride2_floats(*opt, get_parameter_size(key, num_extruders));
|
||||
}
|
||||
|
||||
// BBS
|
||||
@@ -11446,48 +11493,6 @@ void DynamicPrintConfig::update_filament_config_values_for_multiple_extruders(Dy
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Options in printer_options_with_variant_2 are stored as (normal,silent) pairs per printer variant.
|
||||
// Some legacy presets/projects carry a variant list but still store only one pair; normalize to avoid crashes.
|
||||
static void normalize_stride2_floats(ConfigOptionFloats &opt, size_t expected_size)
|
||||
{
|
||||
auto &v = opt.values;
|
||||
if (expected_size == 0) {
|
||||
v.clear();
|
||||
return;
|
||||
}
|
||||
if (v.empty()) {
|
||||
// Fallback: keep behavior predictable instead of crashing. This should be rare.
|
||||
v.resize(expected_size, 0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
const double first = v[0];
|
||||
const double second = (v.size() >= 2) ? v[1] : first;
|
||||
|
||||
// Ensure we have at least one (normal,silent) pair to replicate.
|
||||
if (v.size() < 2) {
|
||||
v.resize(2, first);
|
||||
v[1] = second;
|
||||
}
|
||||
// Keep pair alignment if some legacy preset produced odd length.
|
||||
if (v.size() % 2 != 0)
|
||||
v.push_back(second);
|
||||
|
||||
if (v.size() > expected_size) {
|
||||
v.resize(expected_size);
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t have_variants = v.size() / 2;
|
||||
const size_t want_variants = expected_size / 2;
|
||||
v.resize(expected_size);
|
||||
for (size_t vi = have_variants; vi < want_variants; ++vi) {
|
||||
v[vi * 2] = first;
|
||||
if (vi * 2 + 1 < v.size())
|
||||
v[vi * 2 + 1] = second;
|
||||
}
|
||||
}
|
||||
|
||||
static void log_normalize_legacy_vector_size(const char *fn, const std::string &key, int stride, size_t src_size, size_t dest_size, size_t expected_size,
|
||||
size_t restore_n, int cur_variant_count, int target_variant_count, size_t cur_ids, size_t target_ids,
|
||||
const ConfigOption *opt_src, const ConfigOption *opt_target)
|
||||
|
||||
@@ -1161,8 +1161,9 @@ std::string Tab::options_list_storage_key(const std::string& opt_key) const
|
||||
|
||||
// Orca: deep_diff() flags every vector entry at or past the reference vector's length as changed,
|
||||
// whatever its value (e.g. the values of an extruder added by raising the extruder count). A vector
|
||||
// grows by copying its first entry (ConfigOptionVector::resize), so such an entry only counts as
|
||||
// changed when it differs from the reference's first entry, as before Orca's deep_diff() change.
|
||||
// grows by copying its first entry (ConfigOptionVector::resize), and machine limits by copying their
|
||||
// first (normal, silent) pair (set_num_extruders), so such an entry only counts as changed when it
|
||||
// differs from the reference entry it was copied from, as before Orca's deep_diff() change.
|
||||
// The change of the count itself shows on "extruders_count".
|
||||
static void drop_unchanged_added_entries(std::vector<std::string> &options, const DynamicPrintConfig ¤t, const Preset *reference)
|
||||
{
|
||||
@@ -1171,7 +1172,7 @@ static void drop_unchanged_added_entries(std::vector<std::string> &options, cons
|
||||
// deep_diff() lists a key's entries one after another, so serialize each key's vectors once.
|
||||
std::string serialized_key;
|
||||
std::vector<std::string> cur_values;
|
||||
std::string ref_first;
|
||||
std::vector<std::string> ref_values;
|
||||
options.erase(std::remove_if(options.begin(), options.end(), [&](const std::string &opt) {
|
||||
const auto pos = opt.find('#');
|
||||
if (pos == std::string::npos)
|
||||
@@ -1185,9 +1186,10 @@ static void drop_unchanged_added_entries(std::vector<std::string> &options, cons
|
||||
if (key != serialized_key) {
|
||||
serialized_key = key;
|
||||
cur_values = cur->vserialize();
|
||||
ref_first = ref->vserialize().front();
|
||||
ref_values = ref->vserialize();
|
||||
}
|
||||
return cur_values[idx] == ref_first;
|
||||
const size_t copied_from = printer_options_with_variant_2.count(key) > 0 && idx % 2 < ref_values.size() ? idx % 2 : 0;
|
||||
return cur_values[idx] == ref_values[copied_from];
|
||||
}), options.end());
|
||||
}
|
||||
|
||||
|
||||
@@ -799,3 +799,40 @@ TEST_CASE("A per-variant filament option read with a single value gives it to ev
|
||||
config.load_from_ini_string("pressure_advance = 0.021", ForwardCompatibilitySubstitutionRule::Disable);
|
||||
REQUIRE(config.option<ConfigOptionFloats>("pressure_advance")->values == std::vector<double>({0.021, 0.021, 0.021}));
|
||||
}
|
||||
|
||||
// Machine limits (printer_options_with_variant_2) hold a (normal, silent) pair per printer variant, so the
|
||||
// printer Tab's Motion ability page can edit each extruder's own limits.
|
||||
TEST_CASE("set_num_extruders gives every printer variant its own pair of machine limits", "[Config]")
|
||||
{
|
||||
DynamicPrintConfig config = DynamicPrintConfig::full_print_config();
|
||||
auto speed_x = [&config]() { return config.option<ConfigOptionFloats>("machine_max_speed_x")->values; };
|
||||
|
||||
SECTION("a single pair is copied to every extruder") {
|
||||
config.option<ConfigOptionFloats>("machine_max_speed_x")->values = {500., 200.};
|
||||
config.set_num_extruders(3);
|
||||
REQUIRE(config.option<ConfigOptionStrings>("printer_extruder_variant")->size() == 3);
|
||||
REQUIRE(speed_x() == std::vector<double>({500., 200., 500., 200., 500., 200.}));
|
||||
}
|
||||
|
||||
SECTION("per-extruder pairs are kept, and removing an extruder removes its pair") {
|
||||
config.option<ConfigOptionFloats>("machine_max_speed_x")->values = {500., 200., 400., 150., 300., 100.};
|
||||
config.set_num_extruders(3);
|
||||
REQUIRE(speed_x() == std::vector<double>({500., 200., 400., 150., 300., 100.}));
|
||||
config.set_num_extruders(2);
|
||||
REQUIRE(speed_x() == std::vector<double>({500., 200., 400., 150.}));
|
||||
}
|
||||
|
||||
SECTION("a printer with nozzle variants gets a pair per variant column") {
|
||||
// 2 extruders x 2 variants = 4 columns
|
||||
config.option<ConfigOptionStrings>("extruder_variant_list", true)->values = {"Direct Drive Standard,Direct Drive High Flow",
|
||||
"Direct Drive Standard,Direct Drive High Flow"};
|
||||
const std::vector<double> per_variant = {500., 200., 510., 210., 520., 220., 530., 230.};
|
||||
config.option<ConfigOptionFloats>("machine_max_speed_x")->values = per_variant;
|
||||
config.set_num_extruders(2);
|
||||
REQUIRE(speed_x() == per_variant);
|
||||
|
||||
config.option<ConfigOptionFloats>("machine_max_speed_x")->values = {500., 200.};
|
||||
config.set_num_extruders(2);
|
||||
REQUIRE(speed_x() == std::vector<double>({500., 200., 500., 200., 500., 200., 500., 200.}));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user