mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-16 13:32:44 +00:00
Fix per-obj multi-variant options handling (#14700)
* ENH: config: add logic to apply params to object/region config with multi-extruder JIRA: no-jira Change-Id: Ieab98cd8d031e5ca82a3aad2d0b89d8ae4a794f1 (cherry picked from commit 3179fd416e68ca8bc2d746f859508d07db18fe5b) * FIX: X1C switch to H2D lose Highflow parameter Jira: STUDIO-15272 Change-Id: Id8cf5d93a49d5542ac82f9554974b458e15c1193 (cherry picked from commit 15d9f072ff658a3beb4f916d978dfea12c2d9f16) * Fix mishandling of `stride` param and add unit test for it * Fix modified multi-variant per-obj option highlight * Fix issue that per-obj FloatsOrPercents options are marked as dirty incorrectly when lost focus --------- Co-authored-by: lane.wei <lane.wei@bambulab.com> Co-authored-by: weiting.ji <weiting.ji@bambulab.com>
This commit is contained in:
co-authored by
lane.wei
weiting.ji
parent
22e121f4e4
commit
93d5b65852
@@ -363,6 +363,7 @@ public:
|
|||||||
virtual void set_with_restore(const ConfigOptionVectorBase* rhs, std::vector<int>& restore_index, int stride) = 0;
|
virtual void set_with_restore(const ConfigOptionVectorBase* rhs, std::vector<int>& restore_index, int stride) = 0;
|
||||||
virtual void set_with_restore_2(const ConfigOptionVectorBase* rhs, std::vector<int>& restore_index, int start, int len, bool skip_error = false) = 0;
|
virtual void set_with_restore_2(const ConfigOptionVectorBase* rhs, std::vector<int>& restore_index, int start, int len, bool skip_error = false) = 0;
|
||||||
virtual void set_only_diff(const ConfigOptionVectorBase* rhs, std::vector<int>& diff_index, int stride) = 0;
|
virtual void set_only_diff(const ConfigOptionVectorBase* rhs, std::vector<int>& diff_index, int stride) = 0;
|
||||||
|
virtual void set_to_index(const ConfigOptionVectorBase* rhs, std::vector<int>& dest_index, int stride) = 0;
|
||||||
virtual void set_with_nil(const ConfigOptionVectorBase* rhs, const ConfigOptionVectorBase* inherits, int stride) = 0;
|
virtual void set_with_nil(const ConfigOptionVectorBase* rhs, const ConfigOptionVectorBase* inherits, int stride) = 0;
|
||||||
// Resize the vector of values, copy the newly added values from opt_default if provided.
|
// Resize the vector of values, copy the newly added values from opt_default if provided.
|
||||||
virtual void resize(size_t n, const ConfigOption *opt_default = nullptr) = 0;
|
virtual void resize(size_t n, const ConfigOption *opt_default = nullptr) = 0;
|
||||||
@@ -586,6 +587,32 @@ public:
|
|||||||
throw ConfigurationError("ConfigOptionVector::set_only_diff(): Assigning an incompatible type");
|
throw ConfigurationError("ConfigOptionVector::set_only_diff(): Assigning an incompatible type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//set a item related with extruder variants when apply static config with dynamic config
|
||||||
|
//rhs: item from dynamic config
|
||||||
|
//dest_index: which index in this vector need to be used
|
||||||
|
virtual void set_to_index(const ConfigOptionVectorBase* rhs, std::vector<int>& dest_index, int stride) override
|
||||||
|
{
|
||||||
|
if (rhs->type() == this->type()) {
|
||||||
|
// Assign the first value of the rhs vector.
|
||||||
|
auto other = static_cast<const ConfigOptionVector<T>*>(rhs);
|
||||||
|
T v = other->values.front();
|
||||||
|
this->values.resize(dest_index.size() * stride, v);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < dest_index.size(); i++) {
|
||||||
|
if (dest_index[i] < 0)
|
||||||
|
continue;
|
||||||
|
for (size_t j = 0; j < size_t(stride); j++)
|
||||||
|
{
|
||||||
|
const size_t src_idx = size_t(dest_index[i]) * size_t(stride) + j;
|
||||||
|
if (src_idx < other->values.size() && !other->is_nil(size_t(dest_index[i]) * size_t(stride)))
|
||||||
|
this->values[i * size_t(stride) + j] = other->values[src_idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw ConfigurationError("ConfigOptionVector::set_to_index(): Assigning an incompatible type");
|
||||||
|
}
|
||||||
|
|
||||||
//set a item related with extruder variants when saving user config, set the non-diff value of some extruder to nill
|
//set a item related with extruder variants when saving user config, set the non-diff value of some extruder to nill
|
||||||
//this item has different value with inherit config
|
//this item has different value with inherit config
|
||||||
//rhs: item from userconfig
|
//rhs: item from userconfig
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ public:
|
|||||||
// (layer height, first layer height, raft settings, print nozzle diameter etc).
|
// (layer height, first layer height, raft settings, print nozzle diameter etc).
|
||||||
const SlicingParameters& slicing_parameters() const { return m_slicing_params; }
|
const SlicingParameters& slicing_parameters() const { return m_slicing_params; }
|
||||||
// Orca: XYZ shrinkage compensation has introduced the const Vec3d &object_shrinkage_compensation parameter to the function below
|
// Orca: XYZ shrinkage compensation has introduced the const Vec3d &object_shrinkage_compensation parameter to the function below
|
||||||
static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation);
|
static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation, std::vector<int> variant_index = std::vector<int>());
|
||||||
|
|
||||||
size_t num_printing_regions() const throw() { return m_shared_regions->all_regions.size(); }
|
size_t num_printing_regions() const throw() { return m_shared_regions->all_regions.size(); }
|
||||||
const PrintRegion& printing_region(size_t idx) const throw() { return *m_shared_regions->all_regions[idx].get(); }
|
const PrintRegion& printing_region(size_t idx) const throw() { return *m_shared_regions->all_regions[idx].get(); }
|
||||||
@@ -489,7 +489,7 @@ public:
|
|||||||
// If ! m_slicing_params.valid, recalculate.
|
// If ! m_slicing_params.valid, recalculate.
|
||||||
void update_slicing_parameters();
|
void update_slicing_parameters();
|
||||||
|
|
||||||
static PrintObjectConfig object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders);
|
static PrintObjectConfig object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders, std::vector<int>& variant_index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void make_perimeters();
|
void make_perimeters();
|
||||||
|
|||||||
@@ -724,7 +724,7 @@ PrintObjectRegions::BoundingBox find_modifier_volume_extents(const PrintObjectRe
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_or_parent_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders);
|
PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_or_parent_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders, std::vector<int>& variant_index);
|
||||||
|
|
||||||
void print_region_ref_inc(PrintRegion &r) { ++ r.m_ref_cnt; }
|
void print_region_ref_inc(PrintRegion &r) { ++ r.m_ref_cnt; }
|
||||||
void print_region_ref_reset(PrintRegion &r) { r.m_ref_cnt = 0; }
|
void print_region_ref_reset(PrintRegion &r) { r.m_ref_cnt = 0; }
|
||||||
@@ -738,7 +738,8 @@ bool verify_update_print_object_regions(
|
|||||||
const PrintRegionConfig &default_region_config,
|
const PrintRegionConfig &default_region_config,
|
||||||
size_t num_extruders,
|
size_t num_extruders,
|
||||||
PrintObjectRegions &print_object_regions,
|
PrintObjectRegions &print_object_regions,
|
||||||
const std::function<void(const PrintRegionConfig&, const PrintRegionConfig&, const t_config_option_keys&)> &callback_invalidate)
|
const std::function<void(const PrintRegionConfig&, const PrintRegionConfig&, const t_config_option_keys&)> &callback_invalidate,
|
||||||
|
std::vector<int>& variant_index)
|
||||||
{
|
{
|
||||||
// Sort by ModelVolume ID.
|
// Sort by ModelVolume ID.
|
||||||
model_volumes_sort_by_id(model_volumes);
|
model_volumes_sort_by_id(model_volumes);
|
||||||
@@ -783,7 +784,7 @@ bool verify_update_print_object_regions(
|
|||||||
} else if (PrintObjectRegions::BoundingBox parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); parent_bbox.intersects(*bbox))
|
} else if (PrintObjectRegions::BoundingBox parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); parent_bbox.intersects(*bbox))
|
||||||
// Such parent region does not exist. If it is needed, then we need to reslice.
|
// Such parent region does not exist. If it is needed, then we need to reslice.
|
||||||
// Only create new region for a modifier, which actually modifies config of it's parent.
|
// Only create new region for a modifier, which actually modifies config of it's parent.
|
||||||
if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, **it_model_volume, num_extruders);
|
if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, **it_model_volume, num_extruders, variant_index);
|
||||||
config != parent_region.region->config())
|
config != parent_region.region->config())
|
||||||
// This modifier newly overrides a region, which it did not before. We need to reslice.
|
// This modifier newly overrides a region, which it did not before. We need to reslice.
|
||||||
return false;
|
return false;
|
||||||
@@ -791,8 +792,8 @@ bool verify_update_print_object_regions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintRegionConfig cfg = region.parent == -1 ?
|
PrintRegionConfig cfg = region.parent == -1 ?
|
||||||
region_config_from_model_volume(default_region_config, layer_range.config, **it_model_volume, num_extruders) :
|
region_config_from_model_volume(default_region_config, layer_range.config, **it_model_volume, num_extruders, variant_index) :
|
||||||
region_config_from_model_volume(layer_range.volume_regions[region.parent].region->config(), nullptr, **it_model_volume, num_extruders);
|
region_config_from_model_volume(layer_range.volume_regions[region.parent].region->config(), nullptr, **it_model_volume, num_extruders, variant_index);
|
||||||
if (cfg != region.region->config()) {
|
if (cfg != region.region->config()) {
|
||||||
// Region configuration changed.
|
// Region configuration changed.
|
||||||
if (print_region_ref_cnt(*region.region) == 0) {
|
if (print_region_ref_cnt(*region.region) == 0) {
|
||||||
@@ -964,6 +965,7 @@ static PrintObjectRegions* generate_print_object_regions(
|
|||||||
size_t num_extruders,
|
size_t num_extruders,
|
||||||
const float xy_contour_compensation,
|
const float xy_contour_compensation,
|
||||||
const std::vector<unsigned int> &painting_extruders,
|
const std::vector<unsigned int> &painting_extruders,
|
||||||
|
std::vector<int> &variant_index,
|
||||||
const bool has_painted_fuzzy_skin)
|
const bool has_painted_fuzzy_skin)
|
||||||
{
|
{
|
||||||
// Reuse the old object or generate a new one.
|
// Reuse the old object or generate a new one.
|
||||||
@@ -1022,7 +1024,7 @@ static PrintObjectRegions* generate_print_object_regions(
|
|||||||
// Add a model volume, assign an existing region or generate a new one.
|
// Add a model volume, assign an existing region or generate a new one.
|
||||||
layer_range.volume_regions.push_back({
|
layer_range.volume_regions.push_back({
|
||||||
&volume, -1,
|
&volume, -1,
|
||||||
get_create_region(region_config_from_model_volume(default_region_config, layer_range.config, volume, num_extruders)),
|
get_create_region(region_config_from_model_volume(default_region_config, layer_range.config, volume, num_extruders, variant_index)),
|
||||||
bbox
|
bbox
|
||||||
});
|
});
|
||||||
} else if (volume.is_negative_volume()) {
|
} else if (volume.is_negative_volume()) {
|
||||||
@@ -1039,7 +1041,7 @@ static PrintObjectRegions* generate_print_object_regions(
|
|||||||
if (parent_volume.is_model_part() || parent_volume.is_modifier())
|
if (parent_volume.is_model_part() || parent_volume.is_modifier())
|
||||||
if (PrintObjectRegions::BoundingBox parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); parent_bbox.intersects(*bbox)) {
|
if (PrintObjectRegions::BoundingBox parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); parent_bbox.intersects(*bbox)) {
|
||||||
// Only create new region for a modifier, which actually modifies config of it's parent.
|
// Only create new region for a modifier, which actually modifies config of it's parent.
|
||||||
if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, volume, num_extruders);
|
if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, volume, num_extruders, variant_index);
|
||||||
config != parent_region.region->config()) {
|
config != parent_region.region->config()) {
|
||||||
added = true;
|
added = true;
|
||||||
layer_range.volume_regions.push_back({ &volume, parent_region_id, get_create_region(std::move(config)), bbox });
|
layer_range.volume_regions.push_back({ &volume, parent_region_id, get_create_region(std::move(config)), bbox });
|
||||||
@@ -1162,12 +1164,13 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||||||
}
|
}
|
||||||
|
|
||||||
//apply extruder related values
|
//apply extruder related values
|
||||||
|
std::vector<int> print_variant_index;
|
||||||
if (!extruder_applied) {
|
if (!extruder_applied) {
|
||||||
// variant_2 must be processed first, because variant_1 will make `printer_extruder_id` and `printer_extruder_variant` half of the size that makes `get_index_for_extruder` no longer work properly
|
// variant_2 must be processed first, because variant_1 will make `printer_extruder_id` and `printer_extruder_variant` half of the size that makes `get_index_for_extruder` no longer work properly
|
||||||
new_full_config.update_values_to_printer_extruders(new_full_config, printer_options_with_variant_2, "printer_extruder_id", "printer_extruder_variant", 2);
|
new_full_config.update_values_to_printer_extruders(new_full_config, printer_options_with_variant_2, "printer_extruder_id", "printer_extruder_variant", 2);
|
||||||
new_full_config.update_values_to_printer_extruders(new_full_config, printer_options_with_variant_1, "printer_extruder_id", "printer_extruder_variant");
|
new_full_config.update_values_to_printer_extruders(new_full_config, printer_options_with_variant_1, "printer_extruder_id", "printer_extruder_variant");
|
||||||
//update print config related with variants
|
//update print config related with variants
|
||||||
new_full_config.update_values_to_printer_extruders(new_full_config, print_options_with_variant, "print_extruder_id", "print_extruder_variant");
|
print_variant_index = new_full_config.update_values_to_printer_extruders(new_full_config, print_options_with_variant, "print_extruder_id", "print_extruder_variant");
|
||||||
|
|
||||||
m_ori_full_print_config = new_full_config;
|
m_ori_full_print_config = new_full_config;
|
||||||
new_full_config.update_values_to_printer_extruders_for_multiple_filaments(new_full_config, filament_options_with_variant, "filament_self_index", "filament_extruder_variant");
|
new_full_config.update_values_to_printer_extruders_for_multiple_filaments(new_full_config, filament_options_with_variant, "filament_self_index", "filament_extruder_variant");
|
||||||
@@ -1475,7 +1478,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||||||
if (object_config_changed)
|
if (object_config_changed)
|
||||||
model_object.config.assign_config(model_object_new.config);
|
model_object.config.assign_config(model_object_new.config);
|
||||||
if (! object_diff.empty() || object_config_changed || num_extruders_changed ) {
|
if (! object_diff.empty() || object_config_changed || num_extruders_changed ) {
|
||||||
PrintObjectConfig new_config = PrintObject::object_config_from_model_object(m_default_object_config, model_object, num_extruders );
|
PrintObjectConfig new_config = PrintObject::object_config_from_model_object(m_default_object_config, model_object, num_extruders, print_variant_index);
|
||||||
for (const PrintObjectStatus &print_object_status : print_object_status_db.get_range(model_object)) {
|
for (const PrintObjectStatus &print_object_status : print_object_status_db.get_range(model_object)) {
|
||||||
t_config_option_keys diff = print_object_status.print_object->config().diff(new_config);
|
t_config_option_keys diff = print_object_status.print_object->config().diff(new_config);
|
||||||
if (! diff.empty()) {
|
if (! diff.empty()) {
|
||||||
@@ -1541,10 +1544,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||||||
// Generate a list of trafos and XY offsets for instances of a ModelObject
|
// Generate a list of trafos and XY offsets for instances of a ModelObject
|
||||||
// Producing the config for PrintObject on demand, caching it at print_object_last.
|
// Producing the config for PrintObject on demand, caching it at print_object_last.
|
||||||
const PrintObject *print_object_last = nullptr;
|
const PrintObject *print_object_last = nullptr;
|
||||||
auto print_object_apply_config = [this, &print_object_last, model_object, num_extruders ](PrintObject *print_object) {
|
auto print_object_apply_config = [this, &print_object_last, model_object, num_extruders, &print_variant_index](PrintObject *print_object) {
|
||||||
print_object->config_apply(print_object_last ?
|
print_object->config_apply(print_object_last ?
|
||||||
print_object_last->config() :
|
print_object_last->config() :
|
||||||
PrintObject::object_config_from_model_object(m_default_object_config, *model_object, num_extruders ));
|
PrintObject::object_config_from_model_object(m_default_object_config, *model_object, num_extruders, print_variant_index));
|
||||||
print_object_last = print_object;
|
print_object_last = print_object;
|
||||||
};
|
};
|
||||||
if (old.empty()) {
|
if (old.empty()) {
|
||||||
@@ -1715,7 +1718,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||||||
for (auto it = it_print_object; it != it_print_object_end; ++it)
|
for (auto it = it_print_object; it != it_print_object_end; ++it)
|
||||||
if ((*it)->m_shared_regions != nullptr)
|
if ((*it)->m_shared_regions != nullptr)
|
||||||
update_apply_status((*it)->invalidate_state_by_config_options(old_config, new_config, diff_keys));
|
update_apply_status((*it)->invalidate_state_by_config_options(old_config, new_config, diff_keys));
|
||||||
})) {
|
},
|
||||||
|
print_variant_index)) {
|
||||||
// Regions are valid, just keep them.
|
// Regions are valid, just keep them.
|
||||||
} else {
|
} else {
|
||||||
// Regions were reshuffled.
|
// Regions were reshuffled.
|
||||||
@@ -1737,6 +1741,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||||||
num_extruders ,
|
num_extruders ,
|
||||||
print_object.is_mm_painted() ? 0.f : float(print_object.config().xy_contour_compensation.value),
|
print_object.is_mm_painted() ? 0.f : float(print_object.config().xy_contour_compensation.value),
|
||||||
painting_extruders,
|
painting_extruders,
|
||||||
|
print_variant_index,
|
||||||
print_object.is_fuzzy_skin_painted());
|
print_object.is_fuzzy_skin_painted());
|
||||||
}
|
}
|
||||||
for (auto it = it_print_object; it != it_print_object_end; ++it)
|
for (auto it = it_print_object; it != it_print_object_end; ++it)
|
||||||
|
|||||||
@@ -9602,7 +9602,7 @@ int DynamicPrintConfig::update_values_from_multi_to_multi_2(const std::vector<st
|
|||||||
bool has_value = false;
|
bool has_value = false;
|
||||||
double target_value = std::numeric_limits<double>::max();
|
double target_value = std::numeric_limits<double>::max();
|
||||||
for(auto idx : indices){
|
for(auto idx : indices){
|
||||||
if(opt && !opt->is_nil(idx)){
|
if(opt && idx < opt->values.size() && !opt->is_nil(idx)){
|
||||||
has_value = true;
|
has_value = true;
|
||||||
target_value = std::min(target_value, src_values[idx]);
|
target_value = std::min(target_value, src_values[idx]);
|
||||||
}
|
}
|
||||||
@@ -9789,10 +9789,12 @@ DynamicPrintConfig::get_filament_type() const
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name, unsigned int stride, unsigned int extruder_id)
|
std::vector<int> DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name, unsigned int stride, unsigned int extruder_id)
|
||||||
{
|
{
|
||||||
int extruder_count;
|
int extruder_count;
|
||||||
bool different_extruder = printer_config.support_different_extruders(extruder_count);
|
bool different_extruder = printer_config.support_different_extruders(extruder_count);
|
||||||
|
std::vector<int> variant_index;
|
||||||
|
|
||||||
if ((extruder_count > 1) || different_extruder)
|
if ((extruder_count > 1) || different_extruder)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: different extruders processing")%__LINE__;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: different extruders processing")%__LINE__;
|
||||||
@@ -9803,9 +9805,9 @@ void DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig&
|
|||||||
auto opt_nozzle_volume_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(printer_config.option("nozzle_volume_type"));
|
auto opt_nozzle_volume_type = dynamic_cast<const ConfigOptionEnumsGeneric*>(printer_config.option("nozzle_volume_type"));
|
||||||
if (!opt_extruder_type || !opt_nozzle_volume_type) {
|
if (!opt_extruder_type || !opt_nozzle_volume_type) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: extruder_type or nozzle_volume_type option not found, skipping")%__LINE__;
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: extruder_type or nozzle_volume_type option not found, skipping")%__LINE__;
|
||||||
return;
|
return variant_index;
|
||||||
}
|
}
|
||||||
std::vector<int> variant_index;
|
|
||||||
|
|
||||||
if (extruder_id > 0 && extruder_id <= static_cast<unsigned> (extruder_count)) {
|
if (extruder_id > 0 && extruder_id <= static_cast<unsigned> (extruder_count)) {
|
||||||
variant_index.resize(1);
|
variant_index.resize(1);
|
||||||
@@ -9844,7 +9846,7 @@ void DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig&
|
|||||||
const ConfigDef *config_def = this->def();
|
const ConfigDef *config_def = this->def();
|
||||||
if (!config_def) {
|
if (!config_def) {
|
||||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: can not find config define")%__LINE__;
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: can not find config define")%__LINE__;
|
||||||
return;
|
return variant_index;
|
||||||
}
|
}
|
||||||
for (auto& key: key_set)
|
for (auto& key: key_set)
|
||||||
{
|
{
|
||||||
@@ -9958,6 +9960,8 @@ void DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return variant_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicPrintConfig::update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name)
|
void DynamicPrintConfig::update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name)
|
||||||
@@ -10490,6 +10494,28 @@ void compute_filament_override_value(const std::string& opt_key, const ConfigOpt
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPrintConfig& dest_config, std::vector<int> variant_index, std::set<std::string>& key_set1, int stride)
|
||||||
|
{
|
||||||
|
if (variant_index.size() > 0) {
|
||||||
|
const t_config_option_keys &keys = dest_config.keys();
|
||||||
|
for (auto& opt : keys) {
|
||||||
|
ConfigOption *opt_src = config.option(opt);
|
||||||
|
const ConfigOption *opt_dest = dest_config.option(opt);
|
||||||
|
if (opt_src && opt_dest && (*opt_src != *opt_dest)) {
|
||||||
|
if (opt_dest->is_scalar() || (key_set1.find(opt) == key_set1.end()))
|
||||||
|
opt_src->set(opt_dest);
|
||||||
|
else {
|
||||||
|
ConfigOptionVectorBase* opt_vec_src = static_cast<ConfigOptionVectorBase*>(opt_src);
|
||||||
|
const ConfigOptionVectorBase* opt_vec_dest = static_cast<const ConfigOptionVectorBase*>(opt_dest);
|
||||||
|
opt_vec_src->set_to_index(opt_vec_dest, variant_index, stride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
config.apply(dest_config, true);
|
||||||
|
}
|
||||||
|
|
||||||
//BBS: pass map to recording all invalid valies
|
//BBS: pass map to recording all invalid valies
|
||||||
//FIXME localize this function.
|
//FIXME localize this function.
|
||||||
std::map<std::string, std::string> validate(const FullPrintConfig &cfg, bool under_cli)
|
std::map<std::string, std::string> validate(const FullPrintConfig &cfg, bool under_cli)
|
||||||
|
|||||||
@@ -692,7 +692,7 @@ public:
|
|||||||
bool is_using_different_extruders();
|
bool is_using_different_extruders();
|
||||||
bool support_different_extruders(int& extruder_count) const;
|
bool support_different_extruders(int& extruder_count) const;
|
||||||
int get_index_for_extruder(int extruder_or_filament_id, std::string id_name, ExtruderType extruder_type, NozzleVolumeType nozzle_volume_type, std::string variant_name, unsigned int stride = 1) const;
|
int get_index_for_extruder(int extruder_or_filament_id, std::string id_name, ExtruderType extruder_type, NozzleVolumeType nozzle_volume_type, std::string variant_name, unsigned int stride = 1) const;
|
||||||
void update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name, unsigned int stride = 1, unsigned int extruder_id = 0);
|
std::vector<int> update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name, unsigned int stride = 1, unsigned int extruder_id = 0);
|
||||||
void update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name);
|
void update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, std::set<std::string>& key_set, std::string id_name, std::string variant_name);
|
||||||
|
|
||||||
void update_non_diff_values_to_base_config(DynamicPrintConfig& new_config, const t_config_option_keys& keys, const std::set<std::string>& different_keys, std::string extruder_id_name, std::string extruder_variant_name,
|
void update_non_diff_values_to_base_config(DynamicPrintConfig& new_config, const t_config_option_keys& keys, const std::set<std::string>& different_keys, std::string extruder_id_name, std::string extruder_variant_name,
|
||||||
@@ -719,6 +719,7 @@ extern std::set<std::string> printer_options_with_variant_1;
|
|||||||
extern std::set<std::string> printer_options_with_variant_2;
|
extern std::set<std::string> printer_options_with_variant_2;
|
||||||
extern std::set<std::string> empty_options;
|
extern std::set<std::string> empty_options;
|
||||||
|
|
||||||
|
extern void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPrintConfig& dest_config, std::vector<int> variant_index, std::set<std::string>& key_set1, int stride = 1);
|
||||||
extern void compute_filament_override_value(const std::string& opt_key, const ConfigOption *opt_old_machine, const ConfigOption *opt_new_machine, const ConfigOption *opt_new_filament, const DynamicPrintConfig& new_full_config,
|
extern void compute_filament_override_value(const std::string& opt_key, const ConfigOption *opt_old_machine, const ConfigOption *opt_new_machine, const ConfigOption *opt_new_filament, const DynamicPrintConfig& new_full_config,
|
||||||
t_config_option_keys& diff_keys, DynamicPrintConfig& filament_overrides, std::vector<int>& f_maps);
|
t_config_option_keys& diff_keys, DynamicPrintConfig& filament_overrides, std::vector<int>& f_maps);
|
||||||
|
|
||||||
|
|||||||
@@ -3650,13 +3650,13 @@ static void clamp_feature_filament_to_valid(ConfigOptionInt &opt, size_t num_ext
|
|||||||
opt.value = 1;
|
opt.value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintObjectConfig PrintObject::object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders)
|
PrintObjectConfig PrintObject::object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders, std::vector<int>& variant_index)
|
||||||
{
|
{
|
||||||
PrintObjectConfig config = default_object_config;
|
PrintObjectConfig config = default_object_config;
|
||||||
{
|
{
|
||||||
DynamicPrintConfig src_normalized(object.config.get());
|
DynamicPrintConfig src_normalized(object.config.get());
|
||||||
src_normalized.normalize_fdm();
|
src_normalized.normalize_fdm();
|
||||||
config.apply(src_normalized, true);
|
update_static_print_config_from_dynamic(config, src_normalized, variant_index, print_options_with_variant, 1);
|
||||||
}
|
}
|
||||||
// Clamp invalid extruders to the default extruder (with index 1).
|
// Clamp invalid extruders to the default extruder (with index 1).
|
||||||
clamp_exturder_to_default(config.support_filament, num_extruders);
|
clamp_exturder_to_default(config.support_filament, num_extruders);
|
||||||
@@ -3684,7 +3684,7 @@ struct FeatureFilamentOverrideMask
|
|||||||
bool inner_wall_filament_id = false;
|
bool inner_wall_filament_id = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPrintConfig &in, FeatureFilamentOverrideMask &feature_overrides)
|
static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPrintConfig &in, FeatureFilamentOverrideMask &feature_overrides, std::vector<int>& variant_index)
|
||||||
{
|
{
|
||||||
// 1) Explicit feature filament values take precedence over base extruder fallback.
|
// 1) Explicit feature filament values take precedence over base extruder fallback.
|
||||||
auto *opt_extruder = in.opt<ConfigOptionInt>(key_extruder);
|
auto *opt_extruder = in.opt<ConfigOptionInt>(key_extruder);
|
||||||
@@ -3725,8 +3725,18 @@ static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPr
|
|||||||
else if (it->first == "inner_wall_filament_id")
|
else if (it->first == "inner_wall_filament_id")
|
||||||
feature_overrides.inner_wall_filament_id = false;
|
feature_overrides.inner_wall_filament_id = false;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
my_opt->set(it->second.get());
|
if (*my_opt != *(it->second)) {
|
||||||
|
if (my_opt->is_scalar() || variant_index.empty() || (print_options_with_variant.find(it->first) == print_options_with_variant.end()))
|
||||||
|
my_opt->set(it->second.get());
|
||||||
|
//my_opt->set(it->second.get());
|
||||||
|
else {
|
||||||
|
ConfigOptionVectorBase* opt_vec_src = static_cast<ConfigOptionVectorBase*>(my_opt);
|
||||||
|
const ConfigOptionVectorBase* opt_vec_dest = static_cast<const ConfigOptionVectorBase*>(it->second.get());
|
||||||
|
opt_vec_src->set_to_index(opt_vec_dest, variant_index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3) Apply base extruder only to features that were not explicitly overridden.
|
// 3) Apply base extruder only to features that were not explicitly overridden.
|
||||||
@@ -3746,7 +3756,7 @@ static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_or_parent_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders)
|
PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_or_parent_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders, std::vector<int>& variant_index)
|
||||||
{
|
{
|
||||||
PrintRegionConfig config = default_or_parent_region_config;
|
PrintRegionConfig config = default_or_parent_region_config;
|
||||||
FeatureFilamentOverrideMask feature_overrides;
|
FeatureFilamentOverrideMask feature_overrides;
|
||||||
@@ -3764,17 +3774,17 @@ PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &defau
|
|||||||
if (volume.is_model_part()) {
|
if (volume.is_model_part()) {
|
||||||
// default_or_parent_region_config contains the Print's PrintRegionConfig.
|
// default_or_parent_region_config contains the Print's PrintRegionConfig.
|
||||||
// Override with ModelObject's PrintRegionConfig values.
|
// Override with ModelObject's PrintRegionConfig values.
|
||||||
apply_to_print_region_config(config, volume.get_object()->config.get(), feature_overrides);
|
apply_to_print_region_config(config, volume.get_object()->config.get(), feature_overrides, variant_index);
|
||||||
} else {
|
} else {
|
||||||
// default_or_parent_region_config contains parent PrintRegion config, which already contains ModelVolume's config.
|
// default_or_parent_region_config contains parent PrintRegion config, which already contains ModelVolume's config.
|
||||||
}
|
}
|
||||||
apply_to_print_region_config(config, volume.config.get(), feature_overrides);
|
apply_to_print_region_config(config, volume.config.get(), feature_overrides, variant_index);
|
||||||
if (! volume.material_id().empty())
|
if (! volume.material_id().empty())
|
||||||
apply_to_print_region_config(config, volume.material()->config.get(), feature_overrides);
|
apply_to_print_region_config(config, volume.material()->config.get(), feature_overrides, variant_index);
|
||||||
if (layer_range_config != nullptr) {
|
if (layer_range_config != nullptr) {
|
||||||
// Not applicable to modifiers.
|
// Not applicable to modifiers.
|
||||||
assert(volume.is_model_part());
|
assert(volume.is_model_part());
|
||||||
apply_to_print_region_config(config, *layer_range_config, feature_overrides);
|
apply_to_print_region_config(config, *layer_range_config, feature_overrides, variant_index);
|
||||||
}
|
}
|
||||||
// Resolve feature defaults and clamp invalid extruders to index 1.
|
// Resolve feature defaults and clamp invalid extruders to index 1.
|
||||||
clamp_feature_filament_to_valid(config.sparse_infill_filament_id, num_extruders);
|
clamp_feature_filament_to_valid(config.sparse_infill_filament_id, num_extruders);
|
||||||
@@ -3824,7 +3834,7 @@ void PrintObject::update_slicing_parameters()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Orca: XYZ shrinkage compensation has introduced the const Vec3d &object_shrinkage_compensation parameter to the function below
|
// Orca: XYZ shrinkage compensation has introduced the const Vec3d &object_shrinkage_compensation parameter to the function below
|
||||||
SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation)
|
SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation, std::vector<int> variant_index)
|
||||||
{
|
{
|
||||||
PrintConfig print_config;
|
PrintConfig print_config;
|
||||||
PrintObjectConfig object_config;
|
PrintObjectConfig object_config;
|
||||||
@@ -3834,14 +3844,14 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full
|
|||||||
default_region_config.apply(full_config, true);
|
default_region_config.apply(full_config, true);
|
||||||
// BBS
|
// BBS
|
||||||
size_t filament_extruders = print_config.filament_diameter.size();
|
size_t filament_extruders = print_config.filament_diameter.size();
|
||||||
object_config = object_config_from_model_object(object_config, model_object, filament_extruders);
|
object_config = object_config_from_model_object(object_config, model_object, filament_extruders, variant_index);
|
||||||
|
|
||||||
std::vector<unsigned int> object_extruders;
|
std::vector<unsigned int> object_extruders;
|
||||||
for (const ModelVolume* model_volume : model_object.volumes)
|
for (const ModelVolume* model_volume : model_object.volumes)
|
||||||
if (model_volume->is_model_part()) {
|
if (model_volume->is_model_part()) {
|
||||||
PrintRegion::collect_object_printing_extruders(
|
PrintRegion::collect_object_printing_extruders(
|
||||||
print_config,
|
print_config,
|
||||||
region_config_from_model_volume(default_region_config, nullptr, *model_volume, filament_extruders),
|
region_config_from_model_volume(default_region_config, nullptr, *model_volume, filament_extruders, variant_index),
|
||||||
object_config.brim_type != btNoBrim && object_config.brim_width > 0.,
|
object_config.brim_type != btNoBrim && object_config.brim_width > 0.,
|
||||||
object_extruders);
|
object_extruders);
|
||||||
for (const std::pair<const t_layer_height_range, ModelConfig> &range_and_config : model_object.layer_config_ranges)
|
for (const std::pair<const t_layer_height_range, ModelConfig> &range_and_config : model_object.layer_config_ranges)
|
||||||
@@ -3853,7 +3863,7 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full
|
|||||||
range_and_config.second.has("bottom_surface_filament_id"))
|
range_and_config.second.has("bottom_surface_filament_id"))
|
||||||
PrintRegion::collect_object_printing_extruders(
|
PrintRegion::collect_object_printing_extruders(
|
||||||
print_config,
|
print_config,
|
||||||
region_config_from_model_volume(default_region_config, &range_and_config.second.get(), *model_volume, filament_extruders),
|
region_config_from_model_volume(default_region_config, &range_and_config.second.get(), *model_volume, filament_extruders, variant_index),
|
||||||
object_config.brim_type != btNoBrim && object_config.brim_width > 0.,
|
object_config.brim_type != btNoBrim && object_config.brim_width > 0.,
|
||||||
object_extruders);
|
object_extruders);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -936,6 +936,7 @@ bool TextCtrl::value_was_changed()
|
|||||||
case coString:
|
case coString:
|
||||||
case coStrings:
|
case coStrings:
|
||||||
case coFloatOrPercent:
|
case coFloatOrPercent:
|
||||||
|
case coFloatsOrPercents:
|
||||||
return boost::any_cast<std::string>(m_value) != boost::any_cast<std::string>(val);
|
return boost::any_cast<std::string>(m_value) != boost::any_cast<std::string>(val);
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1184,7 +1184,7 @@ void Tab::update_extruder_switch_colors()
|
|||||||
void Tab::check_extruder_options_status(int index, bool &sys_extruder, bool &modified_extruder, const std::vector<PageShp>& pages_to_check)
|
void Tab::check_extruder_options_status(int index, bool &sys_extruder, bool &modified_extruder, const std::vector<PageShp>& pages_to_check)
|
||||||
{
|
{
|
||||||
int config_index = index;
|
int config_index = index;
|
||||||
if (m_type == Preset::TYPE_PRINT || m_type == Preset::TYPE_PRINTER) {
|
if (m_type == Preset::TYPE_PRINT || m_type == Preset::TYPE_PRINTER || m_type == Preset::TYPE_MODEL) {
|
||||||
int extruder_id;
|
int extruder_id;
|
||||||
NozzleVolumeType nozzle_type;
|
NozzleVolumeType nozzle_type;
|
||||||
parse_extruder_selection(index, extruder_id, nozzle_type);
|
parse_extruder_selection(index, extruder_id, nozzle_type);
|
||||||
|
|||||||
@@ -401,3 +401,212 @@ SCENARIO("update_diff_values_to_child_config tolerates legacy machine-limit vect
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
SCENARIO("ConfigOptionVector::set_to_index with stride=1 copies values correctly", "[Config][set_to_index]") {
|
||||||
|
GIVEN("A destination vector and a source vector with 3 values") {
|
||||||
|
Slic3r::ConfigOptionFloats dest({0.0});
|
||||||
|
Slic3r::ConfigOptionFloats src({10.0, 20.0, 30.0});
|
||||||
|
std::vector<int> variant_index = {0, 1, 2};
|
||||||
|
int stride = 1;
|
||||||
|
|
||||||
|
WHEN("set_to_index is called with stride=1") {
|
||||||
|
dest.set_to_index(&src, variant_index, stride);
|
||||||
|
|
||||||
|
THEN("The destination contains the source values") {
|
||||||
|
REQUIRE(dest.values.size() == 3);
|
||||||
|
REQUIRE(dest.values[0] == 10.0);
|
||||||
|
REQUIRE(dest.values[1] == 20.0);
|
||||||
|
REQUIRE(dest.values[2] == 30.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GIVEN("A destination vector and a source vector with subset mapping") {
|
||||||
|
Slic3r::ConfigOptionFloats dest({0.0});
|
||||||
|
Slic3r::ConfigOptionFloats src({100.0, 200.0, 300.0});
|
||||||
|
std::vector<int> variant_index = {1, 2};
|
||||||
|
int stride = 1;
|
||||||
|
|
||||||
|
WHEN("set_to_index maps only indices 1 and 2") {
|
||||||
|
dest.set_to_index(&src, variant_index, stride);
|
||||||
|
|
||||||
|
THEN("Only the mapped values are copied, default fills the others") {
|
||||||
|
REQUIRE(dest.values.size() == 2);
|
||||||
|
REQUIRE(dest.values[0] == 200.0);
|
||||||
|
REQUIRE(dest.values[1] == 300.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("ConfigOptionVector::set_to_index with stride=2 copies grouped values correctly", "[Config][set_to_index]") {
|
||||||
|
GIVEN("A destination vector and a source vector with stride=2 (e.g., nozzle groups)") {
|
||||||
|
// Source has 4 groups of 2 values each: (10,11), (20,21), (30,31), (40,41)
|
||||||
|
Slic3r::ConfigOptionFloats dest({0.0});
|
||||||
|
Slic3r::ConfigOptionFloats src({10.0, 11.0, 20.0, 21.0, 30.0, 31.0, 40.0, 41.0});
|
||||||
|
int stride = 2;
|
||||||
|
|
||||||
|
WHEN("set_to_index maps groups 0, 1, 3") {
|
||||||
|
std::vector<int> variant_index = {0, 1, 3};
|
||||||
|
dest.set_to_index(&src, variant_index, stride);
|
||||||
|
|
||||||
|
THEN("The destination has 3 groups (6 values) mapped correctly") {
|
||||||
|
REQUIRE(dest.values.size() == 6);
|
||||||
|
// Group 0: (10, 11)
|
||||||
|
REQUIRE(dest.values[0] == 10.0);
|
||||||
|
REQUIRE(dest.values[1] == 11.0);
|
||||||
|
// Group 1: (20, 21)
|
||||||
|
REQUIRE(dest.values[2] == 20.0);
|
||||||
|
REQUIRE(dest.values[3] == 21.0);
|
||||||
|
// Group 3: (40, 41)
|
||||||
|
REQUIRE(dest.values[4] == 40.0);
|
||||||
|
REQUIRE(dest.values[5] == 41.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GIVEN("A destination and a single-group source") {
|
||||||
|
Slic3r::ConfigOptionFloats dest({0.0});
|
||||||
|
// Source has 1 group of 2 values
|
||||||
|
Slic3r::ConfigOptionFloats src({50.0, 60.0});
|
||||||
|
int stride = 2;
|
||||||
|
|
||||||
|
WHEN("set_to_index maps group 0 from a single-group source") {
|
||||||
|
std::vector<int> variant_index = {0};
|
||||||
|
dest.set_to_index(&src, variant_index, stride);
|
||||||
|
|
||||||
|
THEN("The destination contains the single group correctly") {
|
||||||
|
REQUIRE(dest.values.size() == 2);
|
||||||
|
REQUIRE(dest.values[0] == 50.0);
|
||||||
|
REQUIRE(dest.values[1] == 60.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("ConfigOptionVector::set_to_index handles empty dest_index", "[Config][set_to_index]") {
|
||||||
|
GIVEN("A destination and source with stride=2") {
|
||||||
|
Slic3r::ConfigOptionFloats dest({0.0});
|
||||||
|
Slic3r::ConfigOptionFloats src({10.0, 11.0, 20.0, 21.0});
|
||||||
|
std::vector<int> variant_index = {};
|
||||||
|
int stride = 2;
|
||||||
|
|
||||||
|
WHEN("set_to_index is called with an empty index vector") {
|
||||||
|
dest.set_to_index(&src, variant_index, stride);
|
||||||
|
|
||||||
|
THEN("The destination is resized to 0") {
|
||||||
|
REQUIRE(dest.values.size() == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("ConfigOptionVector::set_to_index handles nil values in source", "[Config][set_to_index]") {
|
||||||
|
GIVEN("A source with a nil group (stride=2)") {
|
||||||
|
Slic3r::ConfigOptionFloatsNullable dest({0.0});
|
||||||
|
Slic3r::ConfigOptionFloatsNullable src({10.0, 11.0,
|
||||||
|
Slic3r::ConfigOptionFloatsNullable::nil_value(), Slic3r::ConfigOptionFloatsNullable::nil_value(),
|
||||||
|
30.0, 31.0});
|
||||||
|
int stride = 2;
|
||||||
|
|
||||||
|
WHEN("set_to_index maps all groups including the nil one") {
|
||||||
|
std::vector<int> variant_index = {0, 1, 2};
|
||||||
|
dest.set_to_index(&src, variant_index, stride);
|
||||||
|
|
||||||
|
THEN("Non-nil groups are copied and the nil group keeps the default") {
|
||||||
|
REQUIRE(dest.values.size() == 6);
|
||||||
|
// Group 0: (10, 11) — copied
|
||||||
|
REQUIRE(dest.values[0] == 10.0);
|
||||||
|
REQUIRE(dest.values[1] == 11.0);
|
||||||
|
// Group 1: nil — keeps default (the front value = 10.0)
|
||||||
|
REQUIRE(dest.values[2] == 10.0);
|
||||||
|
REQUIRE(dest.values[3] == 10.0);
|
||||||
|
// Group 2: (30, 31) — copied
|
||||||
|
REQUIRE(dest.values[4] == 30.0);
|
||||||
|
REQUIRE(dest.values[5] == 31.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("ConfigOptionVector::set_to_index handles out-of-bounds dest_index", "[Config][set_to_index]") {
|
||||||
|
GIVEN("A source with only 2 groups (4 values) but dest_index references group 3") {
|
||||||
|
Slic3r::ConfigOptionFloats dest({0.0});
|
||||||
|
Slic3r::ConfigOptionFloats src({10.0, 11.0, 20.0, 21.0}); // 2 groups of stride 2
|
||||||
|
int stride = 2;
|
||||||
|
|
||||||
|
WHEN("set_to_index maps group 3 which is out of bounds") {
|
||||||
|
std::vector<int> variant_index = {0, 3}; // group 3 is out of range
|
||||||
|
dest.set_to_index(&src, variant_index, stride);
|
||||||
|
|
||||||
|
THEN("Group 0 is copied, group 3 falls back to default without crashing") {
|
||||||
|
REQUIRE(dest.values.size() == 4);
|
||||||
|
// Group 0: (10, 11) — copied
|
||||||
|
REQUIRE(dest.values[0] == 10.0);
|
||||||
|
REQUIRE(dest.values[1] == 11.0);
|
||||||
|
// Group 3: out of bounds — keeps default (10.0 = src.values.front())
|
||||||
|
REQUIRE(dest.values[2] == 10.0);
|
||||||
|
REQUIRE(dest.values[3] == 10.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("ConfigOptionVector::set_to_index handles negative dest_index values", "[Config][set_to_index]") {
|
||||||
|
GIVEN("A destination and source with a negative entry in dest_index") {
|
||||||
|
// The dest is initially empty, so resize fills all slots with src.values.front().
|
||||||
|
Slic3r::ConfigOptionFloats dest;
|
||||||
|
Slic3r::ConfigOptionFloats src({100.0, 101.0, 200.0, 201.0});
|
||||||
|
int stride = 2;
|
||||||
|
|
||||||
|
WHEN("set_to_index maps group 0 and a negative index") {
|
||||||
|
std::vector<int> variant_index = {-1, 0};
|
||||||
|
dest.set_to_index(&src, variant_index, stride);
|
||||||
|
|
||||||
|
THEN("The negative index is skipped, the valid group is copied") {
|
||||||
|
REQUIRE(dest.values.size() == 4);
|
||||||
|
// Position 0 (variant_index[0] = -1): skipped, keeps default fill
|
||||||
|
// from resize (src.values.front() = 100.0, applied to all new elements)
|
||||||
|
REQUIRE(dest.values[0] == 100.0);
|
||||||
|
REQUIRE(dest.values[1] == 100.0);
|
||||||
|
// Position 1 (variant_index[1] = 0): copied from group 0 of src
|
||||||
|
REQUIRE(dest.values[2] == 100.0);
|
||||||
|
REQUIRE(dest.values[3] == 101.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("ConfigOptionVector::set_to_index handles single-element groups with stride=1", "[Config][set_to_index]") {
|
||||||
|
GIVEN("A destination re-mapping one variant index with a stride=1 source") {
|
||||||
|
// Simulates the PrintObject.cpp code path: stride=1, variant_index={1}
|
||||||
|
Slic3r::ConfigOptionFloats dest({99.0, 99.0, 99.0, 99.0}); // pre-sized for 4 extruders
|
||||||
|
Slic3r::ConfigOptionFloats src({0.5, 0.6, 0.7, 0.8}); // 4 extruder values
|
||||||
|
std::vector<int> variant_index = {1}; // only extruder 1 is active
|
||||||
|
int stride = 1;
|
||||||
|
|
||||||
|
WHEN("set_to_index is called") {
|
||||||
|
dest.set_to_index(&src, variant_index, stride);
|
||||||
|
|
||||||
|
THEN("Only the mapped value is copied, rest are defaulted") {
|
||||||
|
REQUIRE(dest.values.size() == 1);
|
||||||
|
REQUIRE(dest.values[0] == 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENARIO("ConfigOptionVector::set_to_index throws on incompatible type", "[Config][set_to_index]") {
|
||||||
|
GIVEN("A Floats destination and an Ints source") {
|
||||||
|
Slic3r::ConfigOptionFloats dest({0.0});
|
||||||
|
Slic3r::ConfigOptionInts src({1, 2, 3});
|
||||||
|
std::vector<int> variant_index = {0};
|
||||||
|
int stride = 1;
|
||||||
|
|
||||||
|
WHEN("set_to_index is called with mismatched types") {
|
||||||
|
THEN("A ConfigurationError is thrown") {
|
||||||
|
REQUIRE_THROWS_AS(dest.set_to_index(&src, variant_index, stride), Slic3r::ConfigurationError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user