mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-05 09:07:39 +00:00
Fix post-slice self-invalidation on custom multi-extruder printers
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#define slic3r_Config_hpp_
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <climits>
|
||||
#include <cfloat>
|
||||
@@ -780,10 +781,14 @@ public:
|
||||
this->values[i] = rhs_vec->values[i];
|
||||
modified = true;
|
||||
} else {
|
||||
if ((i < default_index.size()) && (default_index[i] < default_value.size()))
|
||||
// Orca: a negative slot (failed variant lookup) must not silently collapse the
|
||||
// whole array to the first slot's value — the int-vs-size_t comparison used to
|
||||
// promote -1 past the bounds check. Keep the slot's own value (get_at-style
|
||||
// clamp) when no valid index is available.
|
||||
if ((i < default_index.size()) && (default_index[i] >= 0) && (size_t(default_index[i]) < default_value.size()))
|
||||
this->values[i] = default_value[default_index[i]];
|
||||
else
|
||||
this->values[i] = default_value[0];
|
||||
this->values[i] = default_value[std::min(i, default_value.size() - 1)];
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
@@ -2106,6 +2111,11 @@ public:
|
||||
throw ConfigurationError("ConfigOptionEnumGeneric: Assigning an incompatible type");
|
||||
// rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
|
||||
this->value = rhs->getInt();
|
||||
// Orca: options embedded in a StaticPrintConfig are constructed without a keys_map;
|
||||
// adopt the source's so a later serialize() can emit names.
|
||||
if (this->keys_map == nullptr)
|
||||
if (auto rhs_generic = dynamic_cast<const ConfigOptionEnumGeneric *>(rhs))
|
||||
this->keys_map = rhs_generic->keys_map;
|
||||
}
|
||||
|
||||
std::string serialize() const override
|
||||
@@ -2162,7 +2172,12 @@ public:
|
||||
if (rhs->type() != this->type())
|
||||
throw ConfigurationError("ConfigOptionEnumGeneric: Assigning an incompatible type");
|
||||
// rhs could be of the following type: ConfigOptionEnumsGeneric
|
||||
this->values = dynamic_cast<const ConfigOptionEnumsGenericTempl *>(rhs)->values;
|
||||
auto rhs_enums = dynamic_cast<const ConfigOptionEnumsGenericTempl *>(rhs);
|
||||
this->values = rhs_enums->values;
|
||||
// Orca: options embedded in a StaticPrintConfig are constructed without a keys_map;
|
||||
// adopt the source's so a later serialize() emits names instead of empty tokens.
|
||||
if (this->keys_map == nullptr)
|
||||
this->keys_map = rhs_enums->keys_map;
|
||||
}
|
||||
|
||||
std::string serialize() const override
|
||||
|
||||
@@ -3409,7 +3409,11 @@ void Print::update_filament_maps_to_config(std::vector<int> f_maps, std::vector<
|
||||
}
|
||||
else if ((extruder_volume_type_count > extruder_count) && (m_config.filament_volume_map.values.size() > index))
|
||||
nozzle_volume_type = (NozzleVolumeType)(m_config.filament_volume_map.values[index]);
|
||||
m_config.filament_map_2.values[index] = m_ori_full_print_config.get_index_for_extruder(f_maps[index], "print_extruder_id", extruder_type, nozzle_volume_type, "print_extruder_variant");
|
||||
// Orca: when the process variant columns cannot be matched (degenerate
|
||||
// print_extruder_id), key the override by plain extruder index like the seeding
|
||||
// above instead of poisoning the map with -1.
|
||||
int slot_index = m_ori_full_print_config.get_index_for_extruder(f_maps[index], "print_extruder_id", extruder_type, nozzle_volume_type, "print_extruder_variant");
|
||||
m_config.filament_map_2.values[index] = slot_index >= 0 ? slot_index : f_maps[index] - 1;
|
||||
}
|
||||
|
||||
m_full_print_config = m_ori_full_print_config;
|
||||
|
||||
@@ -1355,7 +1355,11 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
if ((extruder_volume_type_count > extruder_count) && opt_filament_volume_maps
|
||||
&& opt_filament_volume_maps->values.size() == filament_maps.size())
|
||||
nozzle_volume_type = (NozzleVolumeType)(opt_filament_volume_maps->values[index]);
|
||||
m_config.filament_map_2.values[index] = new_full_config.get_index_for_extruder(filament_maps[index], "print_extruder_id", extruder_type, nozzle_volume_type, "print_extruder_variant");
|
||||
// Orca: when the process variant columns cannot be matched (degenerate
|
||||
// print_extruder_id), key the override by plain extruder index like the seeding
|
||||
// above instead of poisoning the map with -1.
|
||||
int slot_index = new_full_config.get_index_for_extruder(filament_maps[index], "print_extruder_id", extruder_type, nozzle_volume_type, "print_extruder_variant");
|
||||
m_config.filament_map_2.values[index] = slot_index >= 0 ? slot_index : filament_maps[index] - 1;
|
||||
}
|
||||
|
||||
// Do not use the ApplyStatus as we will use the max function when updating apply_status.
|
||||
@@ -1411,6 +1415,16 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
num_extruders_changed = true;
|
||||
}
|
||||
}
|
||||
else if (! print_diff.empty()) {
|
||||
// Orca: m_config can diverge from an unchanged full config (e.g. the in-slice retract
|
||||
// override recompute writing different values than the apply-time computation). The
|
||||
// invalidation above already fired for print_diff, so repair m_config here as well;
|
||||
// otherwise the divergence is never corrected and every subsequent apply of the same
|
||||
// config invalidates the result again, forever.
|
||||
m_placeholder_parser.apply_config(filament_overrides);
|
||||
m_config.apply_only(new_full_config, print_diff, true);
|
||||
m_config.apply(filament_overrides);
|
||||
}
|
||||
|
||||
ModelObjectStatusDB model_object_status_db;
|
||||
|
||||
|
||||
@@ -10495,6 +10495,44 @@ int DynamicPrintConfig::get_extruder_nozzle_volume_count(int extruder_count, std
|
||||
return count;
|
||||
}
|
||||
|
||||
// Orca: BBL system profiles ship full-width print_extruder_id/print_extruder_variant columns, but
|
||||
// custom multi-extruder printers only ever get the machine-scope columns synthesized for them (see
|
||||
// extend_extruder_variant); the process scope keeps the length-1 defaults, both in presets and in
|
||||
// 3mf project configs. Expanding with that degenerate map makes every per-extruder lookup fail, and
|
||||
// because both keys are themselves in print_options_with_variant, the expansion then latches a
|
||||
// full-width-but-wrong [1,1,...] map that also defeats the generated_extruder_id fallback in
|
||||
// get_index_for_extruder. Synthesize the process columns from the printer's extruder_variant_list
|
||||
// (same token walk as extend_extruder_variant) before expanding.
|
||||
static void ensure_process_variant_columns(DynamicPrintConfig &config, const DynamicPrintConfig &printer_config)
|
||||
{
|
||||
auto id_opt = dynamic_cast<ConfigOptionInts *>(config.option("print_extruder_id"));
|
||||
auto variant_opt = dynamic_cast<ConfigOptionStrings *>(config.option("print_extruder_variant"));
|
||||
auto list_opt = dynamic_cast<const ConfigOptionStrings *>(printer_config.option("extruder_variant_list"));
|
||||
if (!id_opt || !variant_opt || !list_opt)
|
||||
return;
|
||||
if (id_opt->values.size() != 1 || variant_opt->values.size() != 1)
|
||||
return;
|
||||
|
||||
std::vector<int> ids;
|
||||
std::vector<std::string> variants;
|
||||
for (int i = 0; i < int(list_opt->values.size()); ++i) {
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, list_opt->get_at(i), boost::is_any_of(","), boost::token_compress_on);
|
||||
for (std::string &token : tokens) {
|
||||
boost::trim(token);
|
||||
if (token.empty())
|
||||
continue;
|
||||
ids.push_back(i + 1);
|
||||
variants.push_back(token);
|
||||
}
|
||||
}
|
||||
// A single column is the legitimate single-extruder layout, not a degenerate one.
|
||||
if (ids.size() <= 1)
|
||||
return;
|
||||
id_opt->values = std::move(ids);
|
||||
variant_opt->values = std::move(variants);
|
||||
}
|
||||
|
||||
std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& printer_config, int extruder_count, int extruder_nozzle_volume_count, std::vector<std::vector<NozzleVolumeType>>& nv_types,
|
||||
std::set<std::string>& key_set, std::string id_name, std::string variant_name, unsigned int stride, unsigned int extruder_id, NozzleVolumeType filament_nvt)
|
||||
{
|
||||
@@ -10536,6 +10574,8 @@ std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicP
|
||||
variant_count = 1;
|
||||
}
|
||||
else {
|
||||
if (id_name == "print_extruder_id")
|
||||
ensure_process_variant_columns(*this, printer_config);
|
||||
// Orca: emit the slots first, then size variant_count from what was actually
|
||||
// emitted. extruder_nozzle_volume_count only equals the emitted total when every
|
||||
// extruder carries per-type stats; an extruder with an empty stats entry combined
|
||||
|
||||
Reference in New Issue
Block a user