Divided filament for features (#14042)

* Implement legacy key handling to address possible profile issues following semantic change of per feature filaments

* Reimport base

* Fix inner wall

* Profiles update

---------

Co-authored-by: igiannakas <ioannis@my-spot.co.uk>
This commit is contained in:
Ian Bassi
2026-06-05 20:45:43 +08:00
committed by GitHub
co-authored by igiannakas
parent 6667266b44
commit ea35b9ce68
115 changed files with 1167 additions and 604 deletions
+4 -13
View File
@@ -1595,7 +1595,7 @@ int CLI::run(int argc, char **argv)
record_exit_reson(outfile_dir, CLI_FILE_VERSION_NOT_SUPPORTED, 0, cli_errors[CLI_FILE_VERSION_NOT_SUPPORTED], sliced_info);
flush_and_exit(CLI_FILE_VERSION_NOT_SUPPORTED);
}
Semver old_version(1, 5, 9), old_version2(1, 5, 9), old_version3(2, 0, 0), old_version4(2, 2, 0), old_version5("2.4.0");
Semver old_version(1, 5, 9), old_version2(1, 5, 9), old_version3(2, 0, 0), old_version4(2, 2, 0);
if ((file_version < old_version) && !config.empty()) {
translate_old = true;
BOOST_LOG_TRIVIAL(info) << boost::format("old 3mf version %1%, need to translate")%file_version.to_string();
@@ -1610,18 +1610,9 @@ int CLI::run(int argc, char **argv)
BOOST_LOG_TRIVIAL(info) << boost::format("old 3mf version %1%, need to set enable_wrapping_detection to false")%file_version.to_string();
}
if ((file_version < old_version5) && !config.empty()) {
int converted_count = ConfigMigrations::migrate_legacy_feature_filament_defaults(config);
for (ModelObject *model_object : model.objects) {
converted_count += ConfigMigrations::migrate_legacy_feature_filament_defaults(model_object->config);
for (ModelVolume *model_volume : model_object->volumes)
converted_count += ConfigMigrations::migrate_legacy_feature_filament_defaults(model_volume->config);
}
if (converted_count > 0) {
BOOST_LOG_TRIVIAL(info) << boost::format("old 3mf version %1%, migrated %2% feature filament selections from 1 to 0 (Default)") % file_version.to_string() % converted_count;
}
}
// ORCA: legacy feature-filament default migration (1 -> 0) is now handled
// uniformly in PrintConfigDef::handle_legacy() via the old->new key rename
// (wall_filament -> wall_filament_id, etc.), which covers presets too.
if (normative_check) {
ConfigOptionStrings* postprocess_scripts = config.option<ConfigOptionStrings>("post_process");
-28
View File
@@ -2968,34 +2968,6 @@ private:
std::ostream& operator<<(std::ostream& os, const DynamicConfig::DynamicConfigDifference& diff);
namespace ConfigMigrations {
template <typename ConfigLike>
inline int migrate_legacy_feature_filament_defaults(ConfigLike &cfg)
{
static const char *feature_filament_keys[] = {
"wall_filament",
"sparse_infill_filament",
"solid_infill_filament"
};
int converted_count = 0;
for (const char *key : feature_filament_keys) {
if (!cfg.has(key))
continue;
const ConfigOption *opt = cfg.option(key);
if (opt != nullptr && opt->getInt() == 1) {
cfg.set_key_value(key, new ConfigOptionInt(0));
++converted_count;
}
}
return converted_count;
}
}
// Configuration store with a static definition of configuration values.
// In Slic3r, the static configuration stores are during the slicing / g-code generation for efficiency reasons,
// because the configuration values could be accessed directly.
+9 -3
View File
@@ -916,6 +916,12 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
params.extrusion_role = erSolidInfill;
}
}
if (params.extrusion_role == erTopSolidInfill)
params.extruder = region_config.top_surface_filament_id;
else if (params.extrusion_role == erBottomSurface)
params.extruder = region_config.bottom_surface_filament_id;
else if (params.extrusion_role == erSolidInfill)
params.extruder = region_config.internal_solid_filament_id;
// Orca: apply fill multiline only for sparse infill
params.multiline = params.extrusion_role == erInternalInfill ? int(region_config.fill_multiline) : 1;
@@ -1571,12 +1577,12 @@ void Layer::make_ironing()
((config.top_shell_layers > 0 || (this->object()->print()->config().spiral_mode && config.bottom_shell_layers > 1)) &&
(config.ironing_type == IroningType::TopSurfaces ||
(config.ironing_type == IroningType::TopmostOnly && layerm->layer()->upper_layer == nullptr))))) {
if (config.wall_filament == config.solid_infill_filament || config.wall_loops == 0) {
if (config.outer_wall_filament_id == config.top_surface_filament_id || config.wall_loops == 0) {
// Iron the whole face.
ironing_params.extruder = config.solid_infill_filament;
ironing_params.extruder = config.top_surface_filament_id;
} else {
// Iron just the infill.
ironing_params.extruder = config.solid_infill_filament;
ironing_params.extruder = config.top_surface_filament_id;
}
}
if (ironing_params.extruder != -1) {
+72 -43
View File
@@ -4775,6 +4775,7 @@ LayerResult GCode::process_layer(
// Group extrusions by an extruder, then by an object, an island and a region.
std::map<unsigned int, std::vector<ObjectByExtruder>> by_extruder;
std::vector<std::unique_ptr<ExtrusionEntityCollection>> split_perimeter_storage;
bool is_anything_overridden = const_cast<LayerTools&>(layer_tools).wiping_extrusions().is_anything_overridden();
for (const LayerToPrint &layer_to_print : layers) {
if (layer_to_print.support_layer != nullptr) {
@@ -4930,55 +4931,83 @@ LayerResult GCode::process_layer(
if (extrusions->entities.empty()) // This shouldn't happen but first_point() would fail.
continue;
// This extrusion is part of certain Region, which tells us which extruder should be used for it:
int correct_extruder_id = layer_tools.extruder(*extrusions, region);
auto process_extrusions = [&](const ExtrusionEntityCollection *current_extrusions,
const ExtrusionEntityCollection *overrides_key,
bool use_overrides) {
// This extrusion is part of certain Region, which tells us which extruder should be used for it.
int correct_extruder_id = layer_tools.extruder(*current_extrusions, region);
// Let's recover vector of extruder overrides:
const WipingExtrusions::ExtruderPerCopy *entity_overrides = nullptr;
if (! layer_tools.has_extruder(correct_extruder_id)) {
// this entity is not overridden, but its extruder is not in layer_tools - we'll print it
// by last extruder on this layer (could happen e.g. when a wiping object is taller than others - dontcare extruders are eradicated from layer_tools)
correct_extruder_id = layer_tools.extruders.back();
}
printing_extruders.clear();
if (is_anything_overridden) {
entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(extrusions, layer_to_print.original_object, correct_extruder_id, layer_to_print.object()->instances().size());
if (entity_overrides == nullptr) {
const WipingExtrusions::ExtruderPerCopy *entity_overrides = nullptr;
if (! layer_tools.has_extruder(correct_extruder_id)) {
// this entity is not overridden, but its extruder is not in layer_tools - we'll print it
// by last extruder on this layer (could happen e.g. when a wiping object is taller than others - dontcare extruders are eradicated from layer_tools)
correct_extruder_id = layer_tools.extruders.back();
}
printing_extruders.clear();
if (is_anything_overridden && use_overrides) {
entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(overrides_key, layer_to_print.original_object, correct_extruder_id, layer_to_print.object()->instances().size());
if (entity_overrides == nullptr) {
printing_extruders.emplace_back(correct_extruder_id);
} else {
printing_extruders.reserve(entity_overrides->size());
for (int extruder : *entity_overrides)
printing_extruders.emplace_back(extruder >= 0 ?
// at least one copy is overridden to use this extruder
extruder :
// at least one copy would normally be printed with this extruder (see get_extruder_overrides function for explanation)
static_cast<unsigned int>(- extruder - 1));
Slic3r::sort_remove_duplicates(printing_extruders);
}
} else {
printing_extruders.emplace_back(correct_extruder_id);
} else {
printing_extruders.reserve(entity_overrides->size());
for (int extruder : *entity_overrides)
printing_extruders.emplace_back(extruder >= 0 ?
// at least one copy is overridden to use this extruder
extruder :
// at least one copy would normally be printed with this extruder (see get_extruder_overrides function for explanation)
static_cast<unsigned int>(- extruder - 1));
Slic3r::sort_remove_duplicates(printing_extruders);
}
} else
printing_extruders.emplace_back(correct_extruder_id);
// Now we must add this extrusion into the by_extruder map, once for each extruder that will print it:
for (unsigned int extruder : printing_extruders)
{
std::vector<ObjectByExtruder::Island> &islands = object_islands_by_extruder(
by_extruder,
extruder,
&layer_to_print - layers.data(),
layers.size(), n_slices+1);
for (size_t i = 0; i <= n_slices; ++ i) {
bool last = i == n_slices;
size_t island_idx = last ? n_slices : slices_test_order[i];
if (// extrusions->first_point does not fit inside any slice
last ||
// extrusions->first_point fits inside ith slice
point_inside_surface(island_idx, extrusions->first_point())) {
if (islands[island_idx].by_region.empty())
islands[island_idx].by_region.assign(print.num_print_regions(), ObjectByExtruder::Island::Region());
islands[island_idx].by_region[region.print_region_id()].append(entity_type, extrusions, entity_overrides);
break;
// Now we must add this extrusion into the by_extruder map, once for each extruder that will print it.
for (unsigned int extruder : printing_extruders) {
std::vector<ObjectByExtruder::Island> &islands = object_islands_by_extruder(
by_extruder,
extruder,
&layer_to_print - layers.data(),
layers.size(), n_slices + 1);
for (size_t i = 0; i <= n_slices; ++i) {
bool last = i == n_slices;
size_t island_idx = last ? n_slices : slices_test_order[i];
if (last || point_inside_surface(island_idx, current_extrusions->first_point())) {
if (islands[island_idx].by_region.empty())
islands[island_idx].by_region.assign(print.num_print_regions(), ObjectByExtruder::Island::Region());
islands[island_idx].by_region[region.print_region_id()].append(entity_type, current_extrusions, entity_overrides);
break;
}
}
}
};
bool split_mixed_perimeters =
entity_type == ObjectByExtruder::Island::Region::PERIMETERS &&
region.config().outer_wall_filament_id.value != region.config().inner_wall_filament_id.value &&
extrusions->role() == erMixed;
if (split_mixed_perimeters) {
auto outer_perimeters = std::make_unique<ExtrusionEntityCollection>();
auto inner_perimeters = std::make_unique<ExtrusionEntityCollection>();
for (const ExtrusionEntity *entity : extrusions->entities) {
const ExtrusionRole role = entity->role();
if (role == erExternalPerimeter || role == erOverhangPerimeter)
outer_perimeters->append(*entity);
else if (role == erPerimeter)
inner_perimeters->append(*entity);
}
if (!outer_perimeters->entities.empty()) {
split_perimeter_storage.emplace_back(std::move(outer_perimeters));
process_extrusions(split_perimeter_storage.back().get(), nullptr, false);
}
if (!inner_perimeters->entities.empty()) {
split_perimeter_storage.emplace_back(std::move(inner_perimeters));
process_extrusions(split_perimeter_storage.back().get(), nullptr, false);
}
} else {
process_extrusions(extrusions, extrusions, true);
}
}
}
+59 -33
View File
@@ -80,40 +80,54 @@ bool check_filament_printable_after_group(const std::vector<unsigned int> &used_
}
// Return a zero based extruder from the region, or extruder_override if overriden.
unsigned int LayerTools::wall_filament(const PrintRegion &region) const
unsigned int LayerTools::wall_extruder_id(const PrintRegion &region) const
{
assert(region.config().wall_filament.value > 0);
return ((this->extruder_override == 0) ? region.config().wall_filament.value : this->extruder_override) - 1;
assert(region.config().outer_wall_filament_id.value > 0);
return ((this->extruder_override == 0) ? region.config().outer_wall_filament_id.value : this->extruder_override) - 1;
}
unsigned int LayerTools::sparse_infill_filament(const PrintRegion &region) const
unsigned int LayerTools::sparse_infill_filament_id(const PrintRegion &region) const
{
assert(region.config().sparse_infill_filament.value > 0);
return ((this->extruder_override == 0) ? region.config().sparse_infill_filament.value : this->extruder_override) - 1;
assert(region.config().sparse_infill_filament_id.value > 0);
return ((this->extruder_override == 0) ? region.config().sparse_infill_filament_id.value : this->extruder_override) - 1;
}
unsigned int LayerTools::solid_infill_filament(const PrintRegion &region) const
unsigned int LayerTools::internal_solid_filament_id(const PrintRegion &region) const
{
assert(region.config().solid_infill_filament.value > 0);
return ((this->extruder_override == 0) ? region.config().solid_infill_filament.value : this->extruder_override) - 1;
assert(region.config().internal_solid_filament_id.value > 0);
return ((this->extruder_override == 0) ? region.config().internal_solid_filament_id.value : this->extruder_override) - 1;
}
// Returns a zero based extruder this eec should be printed with, according to PrintRegion config or extruder_override if overriden.
unsigned int LayerTools::extruder(const ExtrusionEntityCollection &extrusions, const PrintRegion &region) const
{
assert(region.config().wall_filament.value > 0);
assert(region.config().sparse_infill_filament.value > 0);
assert(region.config().solid_infill_filament.value > 0);
assert(region.config().outer_wall_filament_id.value > 0);
assert(region.config().sparse_infill_filament_id.value > 0);
assert(region.config().internal_solid_filament_id.value > 0);
assert(region.config().top_surface_filament_id.value > 0);
assert(region.config().bottom_surface_filament_id.value > 0);
// 1 based extruder ID.
unsigned int extruder = 1;
if (this->extruder_override == 0) {
if (extrusions.has_infill()) {
if (extrusions.has_solid_infill())
extruder = region.config().solid_infill_filament;
if (extrusions.has_solid_infill()) {
ExtrusionRole role = extrusions.role();
if (role == erTopSolidInfill || role == erIroning)
extruder = region.config().top_surface_filament_id;
else if (role == erBottomSurface)
extruder = region.config().bottom_surface_filament_id;
else
extruder = region.config().internal_solid_filament_id;
} else {
extruder = region.config().sparse_infill_filament_id;
}
} else {
const ExtrusionRole role = extrusions.role();
if (role == erPerimeter)
extruder = region.config().inner_wall_filament_id.value;
else
extruder = region.config().sparse_infill_filament;
} else
extruder = region.config().wall_filament.value;
extruder = region.config().outer_wall_filament_id.value;
}
} else
extruder = this->extruder_override;
@@ -527,7 +541,7 @@ std::vector<unsigned int> ToolOrdering::generate_first_layer_tool_order(const Pr
return tool_order;
for (auto layerm : target_layer->regions()) {
int extruder_id = layerm->region().config().option("wall_filament")->getInt();
int extruder_id = layerm->region().config().option("outer_wall_filament_id")->getInt();
for (auto expoly : layerm->raw_slices) {
const double nozzle_diameter = print.config().nozzle_diameter.get_at(0);
@@ -591,7 +605,7 @@ std::vector<unsigned int> ToolOrdering::generate_first_layer_tool_order(const Pr
return tool_order;
for (auto layerm : target_layer->regions()) {
int extruder_id = layerm->region().config().option("wall_filament")->getInt();
int extruder_id = layerm->region().config().option("outer_wall_filament_id")->getInt();
for (auto expoly : layerm->raw_slices) {
const double nozzle_diameter = object.print()->config().nozzle_diameter.get_at(0);
const coordf_t line_width = object.config().get_abs_value("line_width", nozzle_diameter);
@@ -682,24 +696,32 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
}
if (something_nonoverriddable){
layer_tools.extruders.emplace_back((extruder_override == 0) ? region.config().wall_filament.value : extruder_override);
layer_tools.extruders.emplace_back((extruder_override == 0) ? region.config().outer_wall_filament_id.value : extruder_override);
if (extruder_override == 0 && region.config().wall_loops.value > 1)
layer_tools.extruders.emplace_back(region.config().inner_wall_filament_id.value);
if (layerCount == 0) {
firstLayerExtruders.emplace_back((extruder_override == 0) ? region.config().wall_filament.value : extruder_override);
firstLayerExtruders.emplace_back((extruder_override == 0) ? region.config().outer_wall_filament_id.value : extruder_override);
}
}
layer_tools.has_object = true;
}
bool has_infill = false;
bool has_solid_infill = false;
bool has_infill = false;
bool has_internal_solid = false;
bool has_top_solid_surface = false;
bool has_bottom_surface = false;
bool something_nonoverriddable = false;
for (const ExtrusionEntity *ee : layerm->fills.entities) {
// fill represents infill extrusions of a single island.
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
ExtrusionRole role = fill->entities.empty() ? erNone : fill->entities.front()->role();
if (is_solid_infill(role))
has_solid_infill = true;
if (role == erTopSolidInfill || role == erIroning)
has_top_solid_surface = true;
else if (role == erBottomSurface)
has_bottom_surface = true;
else if (is_solid_infill(role))
has_internal_solid = true;
else if (role != erNone)
has_infill = true;
@@ -711,14 +733,18 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
if (something_nonoverriddable || !m_print_config_ptr) {
if (extruder_override == 0) {
if (has_solid_infill)
layer_tools.extruders.emplace_back(region.config().solid_infill_filament);
if (has_internal_solid)
layer_tools.extruders.emplace_back(region.config().internal_solid_filament_id);
if (has_top_solid_surface)
layer_tools.extruders.emplace_back(region.config().top_surface_filament_id);
if (has_bottom_surface)
layer_tools.extruders.emplace_back(region.config().bottom_surface_filament_id);
if (has_infill)
layer_tools.extruders.emplace_back(region.config().sparse_infill_filament);
} else if (has_solid_infill || has_infill)
layer_tools.extruders.emplace_back(region.config().sparse_infill_filament_id);
} else if (has_internal_solid || has_top_solid_surface || has_bottom_surface || has_infill)
layer_tools.extruders.emplace_back(extruder_override);
}
if (has_solid_infill || has_infill)
if (has_internal_solid || has_top_solid_surface || has_bottom_surface || has_infill)
layer_tools.has_object = true;
}
layerCount++;
@@ -1657,7 +1683,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
if (wipe_into_infill_only && ! is_infill_first)
// In this case we must check that the original extruder is used on this layer before the one we are overridding
// (and the perimeters will be finished before the infill is printed):
if (!lt.is_extruder_order(lt.wall_filament(region), new_extruder))
if (!lt.is_extruder_order(lt.wall_extruder_id(region), new_extruder))
continue;
if ((!is_entity_overridden(fill, object, copy) && fill->total_volume() > min_infill_volume))
@@ -1775,8 +1801,8 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
if (is_infill_first
//BBS
//|| object->config().flush_into_objects // in this case the perimeter is overridden, so we can override by the last one safely
|| lt.is_extruder_order(lt.wall_filament(region), last_nonsoluble_extruder // !infill_first, but perimeter is already printed when last extruder prints
|| ! lt.has_extruder(lt.sparse_infill_filament(region)))) // we have to force override - this could violate infill_first (FIXME)
|| lt.is_extruder_order(lt.wall_extruder_id(region), last_nonsoluble_extruder // !infill_first, but perimeter is already printed when last extruder prints
|| ! lt.has_extruder(lt.sparse_infill_filament_id(region)))) // we have to force override - this could violate infill_first (FIXME)
set_extruder_override(fill, object, copy, (is_infill_first ? first_nonsoluble_extruder : last_nonsoluble_extruder), num_of_copies);
else {
// In this case we can (and should) leave it to be printed normally.
+3 -3
View File
@@ -139,9 +139,9 @@ public:
bool has_extruder(unsigned int extruder) const { return std::find(this->extruders.begin(), this->extruders.end(), extruder) != this->extruders.end(); }
// Return a zero based extruder from the region, or extruder_override if overriden.
unsigned int wall_filament(const PrintRegion &region) const;
unsigned int sparse_infill_filament(const PrintRegion &region) const;
unsigned int solid_infill_filament(const PrintRegion &region) const;
unsigned int wall_extruder_id(const PrintRegion &region) const;
unsigned int sparse_infill_filament_id(const PrintRegion &region) const;
unsigned int internal_solid_filament_id(const PrintRegion &region) const;
// Returns a zero based extruder this eec should be printed with, according to PrintRegion config or extruder_override if overriden.
unsigned int extruder(const ExtrusionEntityCollection &extrusions, const PrintRegion &region) const;
+8 -8
View File
@@ -3881,7 +3881,7 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
for (auto &used : m_used_filament_length) // reset used filament stats
used = 0.f;
int wall_filament = get_wall_filament_for_all_layer();
int wall_filament_id = get_wall_filament_for_all_layer();
std::vector<WipeTower::ToolChangeResult> layer_result;
int index = 0;
@@ -3909,24 +3909,24 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
ToolChangeResult finish_layer_tcr;
ToolChangeResult timelapse_wall;
auto get_wall_filament_for_this_layer = [this, &layer, &wall_filament]() -> int {
auto get_wall_filament_for_this_layer = [this, &layer, &wall_filament_id]() -> int {
if (layer.tool_changes.size() == 0)
return -1;
int candidate_id = -1;
for (size_t idx = 0; idx < layer.tool_changes.size(); ++idx) {
if (idx == 0) {
if (layer.tool_changes[idx].old_tool == wall_filament)
return wall_filament;
else if (m_filpar[layer.tool_changes[idx].old_tool].category == m_filpar[wall_filament].category) {
if (layer.tool_changes[idx].old_tool == wall_filament_id)
return wall_filament_id;
else if (m_filpar[layer.tool_changes[idx].old_tool].category == m_filpar[wall_filament_id].category) {
candidate_id = layer.tool_changes[idx].old_tool;
}
}
if (layer.tool_changes[idx].new_tool == wall_filament) {
return wall_filament;
if (layer.tool_changes[idx].new_tool == wall_filament_id) {
return wall_filament_id;
}
if ((candidate_id == -1) && (m_filpar[layer.tool_changes[idx].new_tool].category == m_filpar[wall_filament].category))
if ((candidate_id == -1) && (m_filpar[layer.tool_changes[idx].new_tool].category == m_filpar[wall_filament_id].category))
candidate_id = layer.tool_changes[idx].new_tool;
}
return candidate_id == -1 ? layer.tool_changes[0].new_tool : candidate_id;
+2 -1
View File
@@ -141,7 +141,8 @@ bool Layer::is_perimeter_compatible(const PrintRegion& a, const PrintRegion& b)
const PrintRegionConfig& config = a.config();
const PrintRegionConfig& other_config = b.config();
return config.wall_filament == other_config.wall_filament
return config.outer_wall_filament_id == other_config.outer_wall_filament_id
&& config.inner_wall_filament_id == other_config.inner_wall_filament_id
&& config.wall_loops == other_config.wall_loops
&& config.wall_sequence == other_config.wall_sequence
&& config.is_infill_first == other_config.is_infill_first
+1 -1
View File
@@ -1345,7 +1345,7 @@ static inline std::vector<std::vector<ExPolygons>> segmentation_top_and_bottom_l
if (const PrintRegionConfig &config = region->region().config();
// color_idx == 0 means "don't know" extruder aka the underlying extruder.
// As this region may split existing regions, we collect statistics over all regions for color_idx == 0.
color_idx == 0 || config.wall_filament == int(color_idx)) {
color_idx == 0 || config.outer_wall_filament_id == int(color_idx)) {
//BBS: the extrusion line width is outer wall rather than inner wall
const double nozzle_diameter = print_object.print()->config().nozzle_diameter.get_at(0);
double outer_wall_line_width = config.get_abs_value("outer_wall_line_width", nozzle_diameter);
+4 -4
View File
@@ -620,7 +620,7 @@ void PerimeterGenerator::split_top_surfaces(const ExPolygons &orig_polygons, ExP
// get the real top surface
ExPolygons grown_lower_slices;
ExPolygons bridge_checker;
auto nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->wall_filament - 1);
auto nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->outer_wall_filament_id - 1);
// Check whether surface be bridge or not
if (this->lower_slices != NULL) {
// BBS: get the Polygons below the polygon this layer
@@ -1173,7 +1173,7 @@ void PerimeterGenerator::process_classic()
// We consider overhang any part where the entire nozzle diameter is not supported by the
// lower layer, so we take lower slices and offset them by half the nozzle diameter used
// in the current layer
double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->wall_filament - 1);
double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->outer_wall_filament_id - 1);
m_lower_slices_polygons = offset(*this->lower_slices, float(scale_(+nozzle_diameter / 2)));
}
@@ -2114,7 +2114,7 @@ void PerimeterGenerator::process_arachne()
// We consider overhang any part where the entire nozzle diameter is not supported by the
// lower layer, so we take lower slices and offset them by half the nozzle diameter used
// in the current layer
double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->wall_filament - 1);
double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->outer_wall_filament_id - 1);
m_lower_slices_polygons = offset(*this->lower_slices, float(scale_(+nozzle_diameter / 2)));
}
@@ -2547,7 +2547,7 @@ bool PerimeterGeneratorLoop::is_internal_contour() const
std::vector<Polygons> PerimeterGenerator::generate_lower_polygons_series(float width)
{
float nozzle_diameter = print_config->nozzle_diameter.get_at(config->wall_filament - 1);
float nozzle_diameter = print_config->nozzle_diameter.get_at(config->outer_wall_filament_id - 1);
float start_offset = -0.5 * width;
float end_offset = 0.5 * nozzle_diameter;
+6 -3
View File
@@ -1072,10 +1072,13 @@ static std::vector<std::string> s_Preset_print_options{
"print_order",
"support_remove_small_overhang",
"filename_format",
"wall_filament",
"outer_wall_filament_id",
"inner_wall_filament_id",
"support_bottom_z_distance",
"sparse_infill_filament",
"solid_infill_filament",
"sparse_infill_filament_id",
"internal_solid_filament_id",
"top_surface_filament_id",
"bottom_surface_filament_id",
"support_filament",
"support_interface_filament",
"support_interface_not_for_body",
+4 -1
View File
@@ -4103,7 +4103,10 @@ DynamicPrintConfig PresetBundle::full_fff_config(bool apply_extruder, std::optio
opt->value = boost::algorithm::clamp<int>(opt->value, 0, int(num_filaments));
}
static const char* keys_with_default[] = {"wall_filament", "sparse_infill_filament", "solid_infill_filament"};
static const char* keys_with_default[] = {
"outer_wall_filament_id", "inner_wall_filament_id", "sparse_infill_filament_id",
"internal_solid_filament_id", "top_surface_filament_id", "bottom_surface_filament_id"
};
for (size_t i = 0; i < sizeof(keys_with_default) / sizeof(keys_with_default[0]); ++ i) {
std::string key = std::string(keys_with_default[i]);
auto *opt = dynamic_cast<ConfigOptionInt*>(out.option(key, false));
+1 -1
View File
@@ -2021,7 +2021,7 @@ Flow Print::brim_flow() const
frPerimeter,
// Flow::new_from_config_width takes care of the percent to value substitution
width,
(float)m_config.nozzle_diameter.get_at(m_print_regions.front()->config().wall_filament-1),
(float)m_config.nozzle_diameter.get_at(m_print_regions.front()->config().outer_wall_filament_id-1),
(float)this->skirt_first_layer_height());
}
+12 -6
View File
@@ -815,9 +815,12 @@ bool verify_update_print_object_regions(
for (const PrintObjectRegions::PaintedRegion &region : layer_range.painted_regions) {
const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[region.parent];
PrintRegionConfig cfg = parent_region.region->config();
cfg.wall_filament.value = region.extruder_id;
cfg.solid_infill_filament.value = region.extruder_id;
cfg.sparse_infill_filament.value = region.extruder_id;
cfg.outer_wall_filament_id.value = region.extruder_id;
cfg.inner_wall_filament_id.value = region.extruder_id;
cfg.internal_solid_filament_id.value = region.extruder_id;
cfg.top_surface_filament_id.value = region.extruder_id;
cfg.bottom_surface_filament_id.value = region.extruder_id;
cfg.sparse_infill_filament_id.value = region.extruder_id;
if (cfg != region.region->config()) {
// Region configuration changed.
if (print_region_ref_cnt(*region.region) == 0) {
@@ -1060,9 +1063,12 @@ static PrintObjectRegions* generate_print_object_regions(
if (const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
parent_region.model_volume->is_model_part() || parent_region.model_volume->is_modifier()) {
PrintRegionConfig cfg = parent_region.region->config();
cfg.wall_filament.value = painted_extruder_id;
cfg.solid_infill_filament.value = painted_extruder_id;
cfg.sparse_infill_filament.value = painted_extruder_id;
cfg.outer_wall_filament_id.value = painted_extruder_id;
cfg.inner_wall_filament_id.value = painted_extruder_id;
cfg.internal_solid_filament_id.value = painted_extruder_id;
cfg.top_surface_filament_id.value = painted_extruder_id;
cfg.bottom_surface_filament_id.value = painted_extruder_id;
cfg.sparse_infill_filament_id.value = painted_extruder_id;
layer_range.painted_regions.push_back({ painted_extruder_id, parent_region_id, get_create_region(std::move(cfg))});
}
// Sort the regions by parent region::print_object_region_id() and extruder_id to help the slicing algorithm when applying MM segmentation.
+120 -29
View File
@@ -4116,7 +4116,7 @@ void PrintConfigDef::init_fff_params()
def->gui_type = ConfigOptionDef::GUIType::one_string;
def->set_default_value(new ConfigOptionPoints());
def = this->add("sparse_infill_filament", coInt);
def = this->add("sparse_infill_filament_id", coInt);
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->label = L("Infill");
def->category = L("Extruders");
@@ -4998,11 +4998,20 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(true));
def = this->add("wall_filament", coInt);
def = this->add("outer_wall_filament_id", coInt);
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->label = L("Walls");
def->label = L("Outer walls");
def->category = L("Extruders");
def->tooltip = L("Filament to print walls.\n\"Default\" uses the active object/part filament.");
def->tooltip = L("Filament to print outer walls.\n\"Default\" uses the active object/part filament.");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(0));
def = this->add("inner_wall_filament_id", coInt);
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->label = L("Inner walls");
def->category = L("Extruders");
def->tooltip = L("Filament to print inner walls.\n\"Default\" uses the active object/part filament.");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(0));
@@ -5759,11 +5768,29 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(15));
def = this->add("solid_infill_filament", coInt);
def = this->add("internal_solid_filament_id", coInt);
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->label = L("Solid infill");
def->label = L("Internal solid infill");
def->category = L("Extruders");
def->tooltip = L("Filament to print solid infill.\n\"Default\" uses the active object/part filament.");
def->tooltip = L("Filament to print internal solid infill.\n\"Default\" uses the active object/part filament.");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(0));
def = this->add("top_surface_filament_id", coInt);
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->label = L("Top surface");
def->category = L("Extruders");
def->tooltip = L("Filament to print top surface.\n\"Default\" uses the active object/part filament.");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(0));
def = this->add("bottom_surface_filament_id", coInt);
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->label = L("Bottom surface");
def->category = L("Extruders");
def->tooltip = L("Filament to print bottom surface.\n\"Default\" uses the active object/part filament.");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(0));
@@ -7995,12 +8022,34 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
opt_key = "change_filament_gcode";
} else if (opt_key == "bridge_fan_speed") {
opt_key = "overhang_fan_speed";
} else if (opt_key == "infill_extruder") {
opt_key = "sparse_infill_filament";
}else if (opt_key == "solid_infill_extruder") {
opt_key = "solid_infill_filament";
}else if (opt_key == "perimeter_extruder") {
opt_key = "wall_filament";
} else if (opt_key == "infill_extruder" || opt_key == "sparse_infill_filament") {
// ORCA: legacy feature-filament selector. Pre-2.4.0-dev these keys were 1-based and the
// default value "1" meant "the first/active filament". The current scheme uses a dedicated
// key where 0 = "Default" (inherit the object/part filament) and 1..N = explicit filament.
// Renaming to the new *_id key here means every config (process presets, 3mf project
// settings, imported gcode) is translated uniformly on load - not just the version-gated
// 3mf paths the old bespoke migration covered - and a brand-new key can never be misread as
// a legacy default. Map the legacy default "1" to "0" (inherit); keep explicit values >1.
opt_key = "sparse_infill_filament_id";
if (value == "1") value = "0";
} else if (opt_key == "solid_infill_extruder" || opt_key == "solid_infill_filament") {
opt_key = "internal_solid_filament_id";
if (value == "1") value = "0";
} else if (opt_key == "top_solid_infill_filament") {
opt_key = "top_surface_filament_id";
if (value == "1") value = "0";
} else if (opt_key == "bottom_solid_infill_filament") {
opt_key = "bottom_surface_filament_id";
if (value == "1") value = "0";
} else if (opt_key == "perimeter_extruder" || opt_key == "wall_filament" || opt_key == "wall_filament_id") {
opt_key = "outer_wall_filament_id";
if (value == "1") value = "0";
} else if (opt_key == "inner_wall_filament") {
opt_key = "inner_wall_filament_id";
if (value == "1") value = "0";
} else if (opt_key == "outer_wall_filament") {
opt_key = "outer_wall_filament_id";
if (value == "1") value = "0";
}else if(opt_key == "wipe_tower_extruder") {
opt_key = "wipe_tower_filament";
}else if (opt_key == "support_material_extruder") {
@@ -8449,10 +8498,18 @@ void DynamicPrintConfig::normalize_fdm(int used_filaments)
int extruder = this->option("extruder")->getInt();
this->erase("extruder");
if (extruder != 0) {
if (!this->has("sparse_infill_filament") || this->option("sparse_infill_filament")->getInt() == 0)
this->option("sparse_infill_filament", true)->setInt(extruder);
if (!this->has("wall_filament") || this->option("wall_filament")->getInt() == 0)
this->option("wall_filament", true)->setInt(extruder);
if (!this->has("sparse_infill_filament_id") || this->option("sparse_infill_filament_id")->getInt() == 0)
this->option("sparse_infill_filament_id", true)->setInt(extruder);
if (!this->has("outer_wall_filament_id") || this->option("outer_wall_filament_id")->getInt() == 0)
this->option("outer_wall_filament_id", true)->setInt(extruder);
if (!this->has("inner_wall_filament_id") || this->option("inner_wall_filament_id")->getInt() == 0)
this->option("inner_wall_filament_id", true)->setInt(extruder);
if (!this->has("internal_solid_filament_id") || this->option("internal_solid_filament_id")->getInt() == 0)
this->option("internal_solid_filament_id", true)->setInt(extruder);
if (!this->has("top_surface_filament_id") || this->option("top_surface_filament_id")->getInt() == 0)
this->option("top_surface_filament_id", true)->setInt(extruder);
if (!this->has("bottom_surface_filament_id") || this->option("bottom_surface_filament_id")->getInt() == 0)
this->option("bottom_surface_filament_id", true)->setInt(extruder);
// Don't propagate the current extruder to support.
// For non-soluble supports, the default "0" extruder means to use the active extruder,
// for soluble supports one certainly does not want to set the extruder to non-soluble.
@@ -8463,12 +8520,25 @@ void DynamicPrintConfig::normalize_fdm(int used_filaments)
}
}
if (this->has("sparse_infill_filament")) {
int sparse_infill_filament = this->option("sparse_infill_filament")->getInt();
if (sparse_infill_filament > 0 && (!this->has("solid_infill_filament") || this->option("solid_infill_filament")->getInt() == 0))
this->option("solid_infill_filament", true)->setInt(sparse_infill_filament);
if (this->has("sparse_infill_filament_id")) {
int sparse_infill_filament_id = this->option("sparse_infill_filament_id")->getInt();
if (sparse_infill_filament_id > 0 && (!this->has("internal_solid_filament_id") || this->option("internal_solid_filament_id")->getInt() == 0))
this->option("internal_solid_filament_id", true)->setInt(sparse_infill_filament_id);
}
const int internal_solid = this->has("internal_solid_filament_id") ? this->option("internal_solid_filament_id")->getInt() : 0;
const int top_surface = this->has("top_surface_filament_id") ? this->option("top_surface_filament_id")->getInt() : 0;
const int bottom_surface = this->has("bottom_surface_filament_id") ? this->option("bottom_surface_filament_id")->getInt() : 0;
if (internal_solid == 0 && top_surface > 0)
this->option("internal_solid_filament_id", true)->setInt(top_surface);
if (internal_solid == 0 && bottom_surface > 0)
this->option("internal_solid_filament_id", true)->setInt(bottom_surface);
if (top_surface == 0 && internal_solid > 0)
this->option("top_surface_filament_id", true)->setInt(internal_solid);
if (bottom_surface == 0 && internal_solid > 0)
this->option("bottom_surface_filament_id", true)->setInt(internal_solid);
if (this->has("spiral_mode") && this->opt<ConfigOptionBool>("spiral_mode", true)->value) {
{
// this should be actually done only on the spiral layers instead of all
@@ -8525,10 +8595,18 @@ void DynamicPrintConfig::normalize_fdm_1()
int extruder = this->option("extruder")->getInt();
this->erase("extruder");
if (extruder != 0) {
if (!this->has("sparse_infill_filament") || this->option("sparse_infill_filament")->getInt() == 0)
this->option("sparse_infill_filament", true)->setInt(extruder);
if (!this->has("wall_filament") || this->option("wall_filament")->getInt() == 0)
this->option("wall_filament", true)->setInt(extruder);
if (!this->has("sparse_infill_filament_id") || this->option("sparse_infill_filament_id")->getInt() == 0)
this->option("sparse_infill_filament_id", true)->setInt(extruder);
if (!this->has("outer_wall_filament_id") || this->option("outer_wall_filament_id")->getInt() == 0)
this->option("outer_wall_filament_id", true)->setInt(extruder);
if (!this->has("inner_wall_filament_id") || this->option("inner_wall_filament_id")->getInt() == 0)
this->option("inner_wall_filament_id", true)->setInt(extruder);
if (!this->has("internal_solid_filament_id") || this->option("internal_solid_filament_id")->getInt() == 0)
this->option("internal_solid_filament_id", true)->setInt(extruder);
if (!this->has("top_surface_filament_id") || this->option("top_surface_filament_id")->getInt() == 0)
this->option("top_surface_filament_id", true)->setInt(extruder);
if (!this->has("bottom_surface_filament_id") || this->option("bottom_surface_filament_id")->getInt() == 0)
this->option("bottom_surface_filament_id", true)->setInt(extruder);
// Don't propagate the current extruder to support.
// For non-soluble supports, the default "0" extruder means to use the active extruder,
// for soluble supports one certainly does not want to set the extruder to non-soluble.
@@ -8539,12 +8617,25 @@ void DynamicPrintConfig::normalize_fdm_1()
}
}
if (this->has("sparse_infill_filament")) {
int sparse_infill_filament = this->option("sparse_infill_filament")->getInt();
if (sparse_infill_filament > 0 && (!this->has("solid_infill_filament") || this->option("solid_infill_filament")->getInt() == 0))
this->option("solid_infill_filament", true)->setInt(sparse_infill_filament);
if (this->has("sparse_infill_filament_id")) {
int sparse_infill_filament_id = this->option("sparse_infill_filament_id")->getInt();
if (sparse_infill_filament_id > 0 && (!this->has("internal_solid_filament_id") || this->option("internal_solid_filament_id")->getInt() == 0))
this->option("internal_solid_filament_id", true)->setInt(sparse_infill_filament_id);
}
const int internal_solid = this->has("internal_solid_filament_id") ? this->option("internal_solid_filament_id")->getInt() : 0;
const int top_surface = this->has("top_surface_filament_id") ? this->option("top_surface_filament_id")->getInt() : 0;
const int bottom_surface = this->has("bottom_surface_filament_id") ? this->option("bottom_surface_filament_id")->getInt() : 0;
if (internal_solid == 0 && top_surface > 0)
this->option("internal_solid_filament_id", true)->setInt(top_surface);
if (internal_solid == 0 && bottom_surface > 0)
this->option("internal_solid_filament_id", true)->setInt(bottom_surface);
if (top_surface == 0 && internal_solid > 0)
this->option("top_surface_filament_id", true)->setInt(internal_solid);
if (bottom_surface == 0 && internal_solid > 0)
this->option("bottom_surface_filament_id", true)->setInt(internal_solid);
if (this->has("spiral_mode") && this->opt<ConfigOptionBool>("spiral_mode", true)->value) {
{
// this should be actually done only on the spiral layers instead of all
+6 -3
View File
@@ -1123,7 +1123,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionPercent, fuzzy_skin_ripple_offset))
((ConfigOptionInt, fuzzy_skin_layers_between_ripple_offset))
((ConfigOptionFloat, gap_infill_speed))
((ConfigOptionInt, sparse_infill_filament))
((ConfigOptionInt, sparse_infill_filament_id))
((ConfigOptionFloatOrPercent, sparse_infill_line_width))
((ConfigOptionPercent, infill_wall_overlap))
((ConfigOptionPercent, top_bottom_infill_wall_overlap))
@@ -1156,14 +1156,17 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloatsNullable, filament_ironing_speed))
// Detect bridging perimeters
((ConfigOptionBool, detect_overhang_wall))
((ConfigOptionInt, wall_filament))
((ConfigOptionInt, outer_wall_filament_id))
((ConfigOptionInt, inner_wall_filament_id))
((ConfigOptionFloatOrPercent, inner_wall_line_width))
((ConfigOptionFloat, inner_wall_speed))
// Total number of perimeters.
((ConfigOptionInt, wall_loops))
((ConfigOptionBool, alternate_extra_wall))
((ConfigOptionFloat, minimum_sparse_infill_area))
((ConfigOptionInt, solid_infill_filament))
((ConfigOptionInt, internal_solid_filament_id))
((ConfigOptionInt, top_surface_filament_id))
((ConfigOptionInt, bottom_surface_filament_id))
((ConfigOptionFloatOrPercent, internal_solid_infill_line_width))
((ConfigOptionFloat, internal_solid_infill_speed))
// Detect thin walls.
+130 -61
View File
@@ -232,7 +232,7 @@ void PrintObject::_transform_hole_to_polyholes()
bool twist = this->m_layers[layer_idx]->m_regions[region_idx]->region().config().hole_to_polyhole_twisted.value;
if (diameter_max - diameter_min < max_variation * 2 && diameter_line_max - diameter_line_min < max_variation * 2) {
layerid2center[layer_idx].emplace_back(
std::tuple<Point, float, int, coord_t, bool>{center, diameter_max, layer->m_regions[region_idx]->region().config().wall_filament.value, max_variation, twist}, & hole);
std::tuple<Point, float, int, coord_t, bool>{center, diameter_max, layer->m_regions[region_idx]->region().config().outer_wall_filament_id.value, max_variation, twist}, & hole);
}
}
}
@@ -316,18 +316,29 @@ std::vector<std::set<int>> PrintObject::detect_extruder_geometric_unprintables()
continue;
for (auto layerm : layer->regions()) {
auto region = layerm->region();
int wall_filament = region.config().wall_filament;
int solid_infill_filament = region.config().solid_infill_filament;
int sparse_infill_filament = region.config().sparse_infill_filament;
int outer_wall_filament_id = region.config().outer_wall_filament_id;
int inner_wall_filament_id = region.config().inner_wall_filament_id;
int internal_solid_filament_id = region.config().internal_solid_filament_id;
int top_surface_filament_id = region.config().top_surface_filament_id;
int bottom_surface_filament_id = region.config().bottom_surface_filament_id;
int sparse_infill_filament_id = region.config().sparse_infill_filament_id;
if (!layerm->fills.entities.empty()) {
if (solid_infill_filament > 0)
geometric_unprintables[extruder_id].insert(solid_infill_filament - 1);
if (sparse_infill_filament > 0)
geometric_unprintables[extruder_id].insert(sparse_infill_filament - 1);
if (internal_solid_filament_id > 0)
geometric_unprintables[extruder_id].insert(internal_solid_filament_id - 1);
if (top_surface_filament_id > 0)
geometric_unprintables[extruder_id].insert(top_surface_filament_id - 1);
if (bottom_surface_filament_id > 0)
geometric_unprintables[extruder_id].insert(bottom_surface_filament_id - 1);
if (sparse_infill_filament_id > 0)
geometric_unprintables[extruder_id].insert(sparse_infill_filament_id - 1);
}
if (!layerm->perimeters.entities.empty()) {
if (outer_wall_filament_id > 0)
geometric_unprintables[extruder_id].insert(outer_wall_filament_id - 1);
if (inner_wall_filament_id > 0)
geometric_unprintables[extruder_id].insert(inner_wall_filament_id - 1);
}
if (!layerm->perimeters.entities.empty() && wall_filament > 0)
geometric_unprintables[extruder_id].insert(wall_filament - 1);
}
}
}
@@ -352,21 +363,28 @@ std::vector<std::set<int>> PrintObject::detect_extruder_geometric_unprintables()
auto layer = m_layers[j];
for (auto layerm : layer->regions()) {
const auto& region = layerm->region();
int wall_filament = region.config().wall_filament;
int solid_infill_filament = region.config().solid_infill_filament;
int sparse_infill_filament = region.config().sparse_infill_filament;
int outer_wall_filament_id = region.config().outer_wall_filament_id;
int inner_wall_filament_id = region.config().inner_wall_filament_id;
int internal_solid_filament_id = region.config().internal_solid_filament_id;
int top_surface_filament_id = region.config().top_surface_filament_id;
int bottom_surface_filament_id = region.config().bottom_surface_filament_id;
int sparse_infill_filament_id = region.config().sparse_infill_filament_id;
std::optional<ExPolygons> fill_expolys;
BoundingBox fill_bbox;
std::optional<ExPolygons> wall_expolys;
BoundingBox wall_bbox;
for (size_t idx = 0; idx < unprintable_area_in_obj_coord.size(); ++idx) {
bool do_infill_filament_detect = (solid_infill_filament > 0 && tbb_geometric_unprintables[idx].count(solid_infill_filament - 1) == 0) ||
(sparse_infill_filament > 0 && tbb_geometric_unprintables[idx].count(sparse_infill_filament-1) == 0);
bool do_infill_filament_detect = (internal_solid_filament_id > 0 && tbb_geometric_unprintables[idx].count(internal_solid_filament_id - 1) == 0) ||
(top_surface_filament_id > 0 && tbb_geometric_unprintables[idx].count(top_surface_filament_id - 1) == 0) ||
(bottom_surface_filament_id > 0 && tbb_geometric_unprintables[idx].count(bottom_surface_filament_id - 1) == 0) ||
(sparse_infill_filament_id > 0 && tbb_geometric_unprintables[idx].count(sparse_infill_filament_id-1) == 0);
bool infill_unprintable = !layerm->fills.entities.empty() &&
((solid_infill_filament > 0 && tbb_geometric_unprintables[idx].count(solid_infill_filament - 1) > 0) ||
(sparse_infill_filament > 0 && tbb_geometric_unprintables[idx].count(sparse_infill_filament - 1) > 0));
((internal_solid_filament_id > 0 && tbb_geometric_unprintables[idx].count(internal_solid_filament_id - 1) > 0) ||
(top_surface_filament_id > 0 && tbb_geometric_unprintables[idx].count(top_surface_filament_id - 1) > 0) ||
(bottom_surface_filament_id > 0 && tbb_geometric_unprintables[idx].count(bottom_surface_filament_id - 1) > 0) ||
(sparse_infill_filament_id > 0 && tbb_geometric_unprintables[idx].count(sparse_infill_filament_id - 1) > 0));
if (!layerm->fills.entities.empty() && do_infill_filament_detect) {
if (!fill_expolys) {
@@ -375,19 +393,27 @@ std::vector<std::set<int>> PrintObject::detect_extruder_geometric_unprintables()
}
if (fill_bbox.overlap(unprintable_area_bbox[idx]) &&
!intersection(*fill_expolys, unprintable_area_in_obj_coord[idx]).empty()) {
if (solid_infill_filament > 0)
tbb_geometric_unprintables[idx].insert(solid_infill_filament - 1);
if (sparse_infill_filament > 0)
tbb_geometric_unprintables[idx].insert(sparse_infill_filament - 1);
if (internal_solid_filament_id > 0)
tbb_geometric_unprintables[idx].insert(internal_solid_filament_id - 1);
if (top_surface_filament_id > 0)
tbb_geometric_unprintables[idx].insert(top_surface_filament_id - 1);
if (bottom_surface_filament_id > 0)
tbb_geometric_unprintables[idx].insert(bottom_surface_filament_id - 1);
if (sparse_infill_filament_id > 0)
tbb_geometric_unprintables[idx].insert(sparse_infill_filament_id - 1);
infill_unprintable = true;
}
}
bool do_wall_filament_detect = wall_filament > 0 && tbb_geometric_unprintables[idx].count(wall_filament - 1) == 0;
if (!layerm->perimeters.entities.empty() && do_wall_filament_detect) {
bool do_outer_wall_filament_detect = outer_wall_filament_id > 0 && tbb_geometric_unprintables[idx].count(outer_wall_filament_id - 1) == 0;
bool do_inner_wall_filament_detect = inner_wall_filament_id > 0 && tbb_geometric_unprintables[idx].count(inner_wall_filament_id - 1) == 0;
if (!layerm->perimeters.entities.empty() && (do_outer_wall_filament_detect || do_inner_wall_filament_detect)) {
// if infill is unprintable, no need to check wall since wall contour surrounds infill contour
if (infill_unprintable) {
tbb_geometric_unprintables[idx].insert(wall_filament - 1);
if (outer_wall_filament_id > 0)
tbb_geometric_unprintables[idx].insert(outer_wall_filament_id - 1);
if (inner_wall_filament_id > 0)
tbb_geometric_unprintables[idx].insert(inner_wall_filament_id - 1);
continue;
}
@@ -402,7 +428,10 @@ std::vector<std::set<int>> PrintObject::detect_extruder_geometric_unprintables()
if (wall_bbox.overlap(unprintable_area_bbox[idx]) &&
!intersection(*wall_expolys, unprintable_area_in_obj_coord[idx]).empty()) {
tbb_geometric_unprintables[idx].insert(wall_filament - 1);
if (outer_wall_filament_id > 0)
tbb_geometric_unprintables[idx].insert(outer_wall_filament_id - 1);
if (inner_wall_filament_id > 0)
tbb_geometric_unprintables[idx].insert(inner_wall_filament_id - 1);
}
}
}
@@ -1263,8 +1292,10 @@ bool PrintObject::invalidate_state_by_config_options(
|| opt_key == "bottom_shell_thickness"
|| opt_key == "top_shell_thickness"
|| opt_key == "minimum_sparse_infill_area"
|| opt_key == "sparse_infill_filament"
|| opt_key == "solid_infill_filament"
|| opt_key == "sparse_infill_filament_id"
|| opt_key == "internal_solid_filament_id"
|| opt_key == "top_surface_filament_id"
|| opt_key == "bottom_surface_filament_id"
|| opt_key == "sparse_infill_line_width"
|| opt_key == "skin_infill_line_width"
|| opt_key == "skeleton_infill_line_width"
@@ -1327,7 +1358,8 @@ bool PrintObject::invalidate_state_by_config_options(
steps.emplace_back(posPrepareInfill);
} else if (
opt_key == "outer_wall_line_width"
|| opt_key == "wall_filament"
|| opt_key == "outer_wall_filament_id"
|| opt_key == "inner_wall_filament_id"
|| opt_key == "fuzzy_skin"
|| opt_key == "fuzzy_skin_thickness"
|| opt_key == "fuzzy_skin_point_distance"
@@ -3548,13 +3580,23 @@ PrintObjectConfig PrintObject::object_config_from_model_object(const PrintObject
}
const std::string key_extruder { "extruder" };
static constexpr const std::initializer_list<const std::string_view> keys_extruders { "sparse_infill_filament"sv, "solid_infill_filament"sv, "wall_filament"sv };
static constexpr const std::initializer_list<const std::string_view> keys_extruders {
"sparse_infill_filament_id"sv,
"internal_solid_filament_id"sv,
"top_surface_filament_id"sv,
"bottom_surface_filament_id"sv,
"outer_wall_filament_id"sv,
"inner_wall_filament_id"sv
};
struct FeatureFilamentOverrideMask
{
bool sparse_infill_filament = false;
bool solid_infill_filament = false;
bool wall_filament = false;
bool sparse_infill_filament_id = false;
bool internal_solid_filament_id = false;
bool top_surface_filament_id = false;
bool bottom_surface_filament_id = false;
bool outer_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)
@@ -3572,19 +3614,31 @@ static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPr
int extruder = static_cast<const ConfigOptionInt*>(it->second.get())->value;
if (extruder > 0) {
my_opt->setInt(extruder);
if (it->first == "sparse_infill_filament")
feature_overrides.sparse_infill_filament = true;
else if (it->first == "solid_infill_filament")
feature_overrides.solid_infill_filament = true;
else if (it->first == "wall_filament")
feature_overrides.wall_filament = true;
if (it->first == "sparse_infill_filament_id")
feature_overrides.sparse_infill_filament_id = true;
else if (it->first == "internal_solid_filament_id")
feature_overrides.internal_solid_filament_id = true;
else if (it->first == "top_surface_filament_id")
feature_overrides.top_surface_filament_id = true;
else if (it->first == "bottom_surface_filament_id")
feature_overrides.bottom_surface_filament_id = true;
else if (it->first == "outer_wall_filament_id")
feature_overrides.outer_wall_filament_id = true;
else if (it->first == "inner_wall_filament_id")
feature_overrides.inner_wall_filament_id = true;
} else {
if (it->first == "sparse_infill_filament")
feature_overrides.sparse_infill_filament = false;
else if (it->first == "solid_infill_filament")
feature_overrides.solid_infill_filament = false;
else if (it->first == "wall_filament")
feature_overrides.wall_filament = false;
if (it->first == "sparse_infill_filament_id")
feature_overrides.sparse_infill_filament_id = false;
else if (it->first == "internal_solid_filament_id")
feature_overrides.internal_solid_filament_id = false;
else if (it->first == "top_surface_filament_id")
feature_overrides.top_surface_filament_id = false;
else if (it->first == "bottom_surface_filament_id")
feature_overrides.bottom_surface_filament_id = false;
else if (it->first == "outer_wall_filament_id")
feature_overrides.outer_wall_filament_id = false;
else if (it->first == "inner_wall_filament_id")
feature_overrides.inner_wall_filament_id = false;
}
} else
my_opt->set(it->second.get());
@@ -3592,12 +3646,18 @@ static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPr
// 3) Apply base extruder only to features that were not explicitly overridden.
if (base_extruder > 0) {
if (!feature_overrides.sparse_infill_filament)
out.sparse_infill_filament.value = base_extruder;
if (!feature_overrides.solid_infill_filament)
out.solid_infill_filament.value = base_extruder;
if (!feature_overrides.wall_filament)
out.wall_filament.value = base_extruder;
if (!feature_overrides.sparse_infill_filament_id)
out.sparse_infill_filament_id.value = base_extruder;
if (!feature_overrides.internal_solid_filament_id)
out.internal_solid_filament_id.value = base_extruder;
if (!feature_overrides.top_surface_filament_id)
out.top_surface_filament_id.value = base_extruder;
if (!feature_overrides.bottom_surface_filament_id)
out.bottom_surface_filament_id.value = base_extruder;
if (!feature_overrides.outer_wall_filament_id)
out.outer_wall_filament_id.value = base_extruder;
if (!feature_overrides.inner_wall_filament_id)
out.inner_wall_filament_id.value = base_extruder;
}
}
@@ -3608,9 +3668,12 @@ PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &defau
// For model parts, non-zero values coming from the print defaults should stay explicit.
if (volume.is_model_part()) {
feature_overrides.sparse_infill_filament = (config.sparse_infill_filament.value > 0);
feature_overrides.solid_infill_filament = (config.solid_infill_filament.value > 0);
feature_overrides.wall_filament = (config.wall_filament.value > 0);
feature_overrides.sparse_infill_filament_id = (config.sparse_infill_filament_id.value > 0);
feature_overrides.internal_solid_filament_id = (config.internal_solid_filament_id.value > 0);
feature_overrides.top_surface_filament_id = (config.top_surface_filament_id.value > 0);
feature_overrides.bottom_surface_filament_id = (config.bottom_surface_filament_id.value > 0);
feature_overrides.outer_wall_filament_id = (config.outer_wall_filament_id.value > 0);
feature_overrides.inner_wall_filament_id = (config.inner_wall_filament_id.value > 0);
}
if (volume.is_model_part()) {
@@ -3629,9 +3692,12 @@ PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &defau
apply_to_print_region_config(config, *layer_range_config, feature_overrides);
}
// Resolve feature defaults and clamp invalid extruders to index 1.
clamp_feature_filament_to_valid(config.sparse_infill_filament, num_extruders);
clamp_feature_filament_to_valid(config.wall_filament, num_extruders);
clamp_feature_filament_to_valid(config.solid_infill_filament, num_extruders);
clamp_feature_filament_to_valid(config.sparse_infill_filament_id, num_extruders);
clamp_feature_filament_to_valid(config.outer_wall_filament_id, num_extruders);
clamp_feature_filament_to_valid(config.inner_wall_filament_id, num_extruders);
clamp_feature_filament_to_valid(config.internal_solid_filament_id, num_extruders);
clamp_feature_filament_to_valid(config.top_surface_filament_id, num_extruders);
clamp_feature_filament_to_valid(config.bottom_surface_filament_id, num_extruders);
if (config.sparse_infill_density.value < 0.00011f)
// Switch of infill for very low infill rates, also avoid division by zero in infill generator for these very low rates.
// See GH issue #5910.
@@ -3694,9 +3760,12 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full
object_config.brim_type != btNoBrim && object_config.brim_width > 0.,
object_extruders);
for (const std::pair<const t_layer_height_range, ModelConfig> &range_and_config : model_object.layer_config_ranges)
if (range_and_config.second.has("wall_filament") ||
range_and_config.second.has("sparse_infill_filament") ||
range_and_config.second.has("solid_infill_filament"))
if (range_and_config.second.has("outer_wall_filament_id") ||
range_and_config.second.has("inner_wall_filament_id") ||
range_and_config.second.has("sparse_infill_filament_id") ||
range_and_config.second.has("internal_solid_filament_id") ||
range_and_config.second.has("top_surface_filament_id") ||
range_and_config.second.has("bottom_surface_filament_id"))
PrintRegion::collect_object_printing_extruders(
print_config,
region_config_from_model_volume(default_region_config, &range_and_config.second.get(), *model_volume, filament_extruders),
@@ -4113,8 +4182,8 @@ void PrintObject::combine_infill()
// Limit the number of combined layers to the maximum height allowed by this regions' nozzle.
//FIXME limit the layer height to max_layer_height
double nozzle_diameter = std::min(
this->print()->config().nozzle_diameter.get_at(region.config().sparse_infill_filament.value - 1),
this->print()->config().nozzle_diameter.get_at(region.config().solid_infill_filament.value - 1));
this->print()->config().nozzle_diameter.get_at(region.config().sparse_infill_filament_id.value - 1),
this->print()->config().nozzle_diameter.get_at(region.config().internal_solid_filament_id.value - 1));
//Orca: Limit combination of infill to up to infill_combination_max_layer_height
const double infill_combination_max_layer_height = region.config().infill_combination_max_layer_height.get_abs_value(nozzle_diameter);
+33 -16
View File
@@ -7,12 +7,16 @@ namespace Slic3r {
unsigned int PrintRegion::extruder(FlowRole role) const
{
size_t extruder = 0;
if (role == frPerimeter || role == frExternalPerimeter)
extruder = m_config.wall_filament;
if (role == frPerimeter)
extruder = m_config.inner_wall_filament_id;
else if (role == frExternalPerimeter)
extruder = m_config.outer_wall_filament_id;
else if (role == frInfill)
extruder = m_config.sparse_infill_filament;
else if (role == frSolidInfill || role == frTopSolidInfill)
extruder = m_config.solid_infill_filament;
extruder = m_config.sparse_infill_filament_id;
else if (role == frSolidInfill)
extruder = m_config.internal_solid_filament_id;
else if (role == frTopSolidInfill)
extruder = m_config.top_surface_filament_id;
else
throw Slic3r::InvalidArgument("Unknown role");
return extruder;
@@ -51,9 +55,12 @@ Flow PrintRegion::flow(const PrintObject &object, FlowRole role, double layer_he
coordf_t PrintRegion::nozzle_dmr_avg(const PrintConfig &print_config) const
{
return (print_config.nozzle_diameter.get_at(m_config.wall_filament.value - 1) +
print_config.nozzle_diameter.get_at(m_config.sparse_infill_filament.value - 1) +
print_config.nozzle_diameter.get_at(m_config.solid_infill_filament.value - 1)) / 3.;
return (print_config.nozzle_diameter.get_at(m_config.outer_wall_filament_id.value - 1) +
print_config.nozzle_diameter.get_at(m_config.inner_wall_filament_id.value - 1) +
print_config.nozzle_diameter.get_at(m_config.sparse_infill_filament_id.value - 1) +
print_config.nozzle_diameter.get_at(m_config.internal_solid_filament_id.value - 1) +
print_config.nozzle_diameter.get_at(m_config.top_surface_filament_id.value - 1) +
print_config.nozzle_diameter.get_at(m_config.bottom_surface_filament_id.value - 1)) / 6.;
}
coordf_t PrintRegion::bridging_height_avg(const PrintConfig &print_config) const
@@ -70,12 +77,19 @@ void PrintRegion::collect_object_printing_extruders(const PrintConfig &print_con
int i = std::max(0, extruder_id - 1);
object_extruders.emplace_back((i >= num_extruders) ? 0 : i);
};
if (region_config.wall_loops.value > 0 || has_brim)
emplace_extruder(region_config.wall_filament);
if (region_config.wall_loops.value > 0 || has_brim) {
emplace_extruder(region_config.outer_wall_filament_id);
if (region_config.wall_loops.value > 1)
emplace_extruder(region_config.inner_wall_filament_id);
}
if (region_config.sparse_infill_density.value > 0)
emplace_extruder(region_config.sparse_infill_filament);
if (region_config.top_shell_layers.value > 0 || region_config.bottom_shell_layers.value > 0)
emplace_extruder(region_config.solid_infill_filament);
emplace_extruder(region_config.sparse_infill_filament_id);
if (region_config.sparse_infill_density.value > 0 || region_config.top_shell_layers.value > 0 || region_config.bottom_shell_layers.value > 0)
emplace_extruder(region_config.internal_solid_filament_id);
if (region_config.top_shell_layers.value > 0)
emplace_extruder(region_config.top_surface_filament_id);
if (region_config.bottom_shell_layers.value > 0)
emplace_extruder(region_config.bottom_surface_filament_id);
}
void PrintRegion::collect_object_printing_extruders(const Print &print, std::vector<unsigned int> &object_extruders) const
@@ -85,9 +99,12 @@ void PrintRegion::collect_object_printing_extruders(const Print &print, std::vec
#ifndef NDEBUG
// BBS
auto num_extruders = int(print.config().filament_diameter.size());
assert(this->config().wall_filament <= num_extruders);
assert(this->config().sparse_infill_filament <= num_extruders);
assert(this->config().solid_infill_filament <= num_extruders);
assert(this->config().outer_wall_filament_id <= num_extruders);
assert(this->config().inner_wall_filament_id <= num_extruders);
assert(this->config().sparse_infill_filament_id <= num_extruders);
assert(this->config().internal_solid_filament_id <= num_extruders);
assert(this->config().top_surface_filament_id <= num_extruders);
assert(this->config().bottom_surface_filament_id <= num_extruders);
#endif
collect_object_printing_extruders(print.config(), this->config(), print.has_brim(), object_extruders);
}
+1 -1
View File
@@ -1226,7 +1226,7 @@ namespace SupportMaterialInternal {
// Surface supporting this layer, expanded by 0.5 * nozzle_diameter, as we consider this kind of overhang to be sufficiently supported.
Polygons lower_grown_slices = expand(lower_layer_polygons,
//FIXME to mimic the decision in the perimeter generator, we should use half the external perimeter width.
0.5f * float(scale_(print_config.nozzle_diameter.get_at(layerm.region().config().wall_filament-1))),
0.5f * float(scale_(print_config.nozzle_diameter.get_at(layerm.region().config().outer_wall_filament_id-1))),
SUPPORT_SURFACES_OFFSET_PARAMETERS);
// Collect perimeters of this layer.
//FIXME split_at_first_point() could split a bridge mid-way
+3 -3
View File
@@ -998,10 +998,10 @@ float GLVolumeCollection::get_selection_support_normal_z() const
} else { // For normal supports, if the angle is set to 0, calculate normal_z from overlap.
const double layer_height = full_cfg.opt_float("layer_height");
const auto* nozzle_diameter_opt = full_cfg.option<ConfigOptionFloats>("nozzle_diameter");
const int wall_filament = full_cfg.opt_int("wall_filament");
const int wall_filament_id = full_cfg.opt_int("outer_wall_filament_id");
const size_t nozzle_count = nozzle_diameter_opt->values.size();
const size_t wall_extruder_idx = (wall_filament > 0 && wall_filament <= static_cast<int>(nozzle_count))
? static_cast<size_t>(wall_filament - 1)
const size_t wall_extruder_idx = (wall_filament_id > 0 && wall_filament_id <= static_cast<int>(nozzle_count))
? static_cast<size_t>(wall_filament_id - 1)
: 0; // Invalid extruder index falls back to extruder 1.
// Use wall extruder's nozzle diameter for better estimation of external perimeter width,
+6 -5
View File
@@ -592,9 +592,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
toggle_field(el, have_perimeters);
bool have_infill = config->option<ConfigOptionPercent>("sparse_infill_density")->value > 0;
// sparse_infill_filament uses the same logic as in Print::extruders()
// sparse_infill_filament_id uses the same logic as in Print::extruders()
for (auto el : { "sparse_infill_pattern", "infill_combination", "fill_multiline","infill_direction",
"minimum_sparse_infill_area", "sparse_infill_filament", "infill_anchor", "infill_anchor_max","infill_shift_step","sparse_infill_rotate_template","symmetric_infill_y_axis"})
"minimum_sparse_infill_area", "sparse_infill_filament_id", "infill_anchor", "infill_anchor_max","infill_shift_step","sparse_infill_rotate_template","symmetric_infill_y_axis"})
toggle_line(el, have_infill);
bool have_combined_infill = config->opt_bool("infill_combination") && have_infill;
@@ -656,7 +656,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
for (auto el : { "infill_direction", "sparse_infill_line_width", "gap_fill_target","filter_out_gap_fill","infill_wall_overlap",
"sparse_infill_speed", "bridge_speed", "internal_bridge_speed", "bridge_angle", "internal_bridge_angle", "relative_bridge_angle",
"solid_infill_direction", "solid_infill_rotate_template", "internal_solid_infill_pattern", "solid_infill_filament",
"solid_infill_direction", "solid_infill_rotate_template", "internal_solid_infill_pattern", "internal_solid_filament_id", "top_surface_filament_id", "bottom_surface_filament_id",
})
toggle_field(el, have_infill || has_solid_infill);
@@ -711,8 +711,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
config->opt_enum<BrimType>("brim_type") != btPainted;
toggle_field("brim_width", have_brim_width);
toggle_field("brim_flow_ratio", have_brim);
// wall_filament uses the same logic as in Print::extruders()
toggle_field("wall_filament", have_perimeters || have_brim);
// Wall filament selectors use the same logic as in Print::extruders().
toggle_field("outer_wall_filament_id", have_perimeters || have_brim);
toggle_field("inner_wall_filament_id", have_perimeters || have_brim);
bool have_brim_ear = (config->opt_enum<BrimType>("brim_type") == btEar);
const auto brim_width = config->opt_float("brim_width");
@@ -705,7 +705,7 @@ static void convert_object_to_vertices(const Slic3r::PrintObject& object, const
continue;
const Slic3r::PrintRegionConfig& cfg = layerm->region().config();
if (has_perimeters) {
const size_t extruder_id = static_cast<size_t>(std::max(cfg.wall_filament.value - 1, 0));
const size_t extruder_id = static_cast<size_t>(std::max(cfg.outer_wall_filament_id.value - 1, 0));
convert_to_vertices(layerm->perimeters, layer_z, layer_id, extruder_id,
object_helper.color_id(layer_z, extruder_id), EGCodeExtrusionRole::ExternalPerimeter,
copy, data.vertices);
@@ -715,10 +715,13 @@ static void convert_object_to_vertices(const Slic3r::PrintObject& object, const
// fill represents infill extrusions of a single island.
const auto& fill = *dynamic_cast<const Slic3r::ExtrusionEntityCollection*>(ee);
if (!fill.entities.empty()) {
const bool is_solid_infill = Slic3r::is_solid_infill(fill.entities.front()->role());
const Slic3r::ExtrusionRole role = fill.entities.front()->role();
const bool is_solid_infill = Slic3r::is_solid_infill(role);
const size_t extruder_id = is_solid_infill ?
static_cast<size_t>(std::max(cfg.solid_infill_filament.value - 1, 0)) :
static_cast<size_t>(std::max(cfg.sparse_infill_filament.value - 1, 0));
static_cast<size_t>(std::max((role == Slic3r::erTopSolidInfill || role == Slic3r::erIroning ? cfg.top_surface_filament_id.value :
role == Slic3r::erBottomSurface ? cfg.bottom_surface_filament_id.value :
cfg.internal_solid_filament_id.value) - 1, 0)) :
static_cast<size_t>(std::max(cfg.sparse_infill_filament_id.value - 1, 0));
convert_to_vertices(fill, layer_z, layer_id, extruder_id,
object_helper.color_id(layer_z, extruder_id),
is_solid_infill ? EGCodeExtrusionRole::SolidInfill : EGCodeExtrusionRole::InternalInfill,
+118 -40
View File
@@ -1517,9 +1517,16 @@ std::vector<int> PartPlate::get_extruders(bool conside_custom_gcode) const
const DynamicPrintConfig& glb_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
int glb_support_intf_extr = glb_config.opt_int("support_interface_filament");
int glb_support_extr = glb_config.opt_int("support_filament");
int glb_wall_extr = glb_config.opt_int("wall_filament");
int glb_sparse_infill_extr = glb_config.opt_int("sparse_infill_filament");
int glb_solid_infill_extr = glb_config.opt_int("solid_infill_filament");
int glb_outer_wall_extr = glb_config.opt_int("outer_wall_filament_id");
int glb_inner_wall_extr = glb_config.opt_int("inner_wall_filament_id");
if (glb_outer_wall_extr == 0) glb_outer_wall_extr = glb_inner_wall_extr;
if (glb_inner_wall_extr == 0) glb_inner_wall_extr = glb_outer_wall_extr;
int glb_sparse_infill_extr = glb_config.opt_int("sparse_infill_filament_id");
int glb_internal_solid_extr = glb_config.opt_int("internal_solid_filament_id");
int glb_top_surface_extr = glb_config.opt_int("top_surface_filament_id");
int glb_bottom_surface_extr = glb_config.opt_int("bottom_surface_filament_id");
if (glb_top_surface_extr == 0) glb_top_surface_extr = glb_internal_solid_extr;
if (glb_bottom_surface_extr == 0) glb_bottom_surface_extr = glb_internal_solid_extr;
bool glb_support = glb_config.opt_bool("enable_support");
glb_support |= glb_config.opt_int("raft_layers") > 0;
@@ -1573,17 +1580,30 @@ std::vector<int> PartPlate::get_extruders(bool conside_custom_gcode) const
plate_extruders.push_back(glb_support_extr);
}
int obj_wall_extr = 0;
const ConfigOption* wall_opt = mo->config.option("wall_filament");
if (wall_opt != nullptr)
obj_wall_extr = wall_opt->getInt();
if (obj_wall_extr != 0)
plate_extruders.push_back(obj_wall_extr);
else if (glb_wall_extr != 0)
plate_extruders.push_back(glb_wall_extr);
int obj_outer_wall_extr = 0;
if (const ConfigOption* wall_opt = mo->config.option("outer_wall_filament_id"); wall_opt != nullptr)
obj_outer_wall_extr = wall_opt->getInt();
if (obj_outer_wall_extr == 0)
if (const ConfigOption* wall_opt = mo->config.option("inner_wall_filament_id"); wall_opt != nullptr)
obj_outer_wall_extr = wall_opt->getInt();
if (obj_outer_wall_extr != 0)
plate_extruders.push_back(obj_outer_wall_extr);
else if (glb_outer_wall_extr != 0)
plate_extruders.push_back(glb_outer_wall_extr);
int obj_inner_wall_extr = 0;
if (const ConfigOption* wall_opt = mo->config.option("inner_wall_filament_id"); wall_opt != nullptr)
obj_inner_wall_extr = wall_opt->getInt();
if (obj_inner_wall_extr == 0)
if (const ConfigOption* wall_opt = mo->config.option("outer_wall_filament_id"); wall_opt != nullptr)
obj_inner_wall_extr = wall_opt->getInt();
if (obj_inner_wall_extr != 0)
plate_extruders.push_back(obj_inner_wall_extr);
else if (glb_inner_wall_extr != 0)
plate_extruders.push_back(glb_inner_wall_extr);
int obj_sparse_infill_extr = 0;
const ConfigOption* sparse_infill_opt = mo->config.option("sparse_infill_filament");
const ConfigOption* sparse_infill_opt = mo->config.option("sparse_infill_filament_id");
if (sparse_infill_opt != nullptr)
obj_sparse_infill_extr = sparse_infill_opt->getInt();
if (obj_sparse_infill_extr != 0)
@@ -1591,14 +1611,33 @@ std::vector<int> PartPlate::get_extruders(bool conside_custom_gcode) const
else if (glb_sparse_infill_extr != 0)
plate_extruders.push_back(glb_sparse_infill_extr);
int obj_solid_infill_extr = 0;
const ConfigOption* solid_infill_opt = mo->config.option("solid_infill_filament");
if (solid_infill_opt != nullptr)
obj_solid_infill_extr = solid_infill_opt->getInt();
if (obj_solid_infill_extr != 0)
plate_extruders.push_back(obj_solid_infill_extr);
else if (glb_solid_infill_extr != 0)
plate_extruders.push_back(glb_solid_infill_extr);
int obj_internal_solid_extr = 0;
if (const ConfigOption* solid_opt = mo->config.option("internal_solid_filament_id"); solid_opt != nullptr)
obj_internal_solid_extr = solid_opt->getInt();
if (obj_internal_solid_extr != 0)
plate_extruders.push_back(obj_internal_solid_extr);
else if (glb_internal_solid_extr != 0)
plate_extruders.push_back(glb_internal_solid_extr);
int obj_top_surface_extr = 0;
if (const ConfigOption* top_opt = mo->config.option("top_surface_filament_id"); top_opt != nullptr)
obj_top_surface_extr = top_opt->getInt();
if (obj_top_surface_extr == 0)
obj_top_surface_extr = obj_internal_solid_extr;
if (obj_top_surface_extr != 0)
plate_extruders.push_back(obj_top_surface_extr);
else if (glb_top_surface_extr != 0)
plate_extruders.push_back(glb_top_surface_extr);
int obj_bottom_surface_extr = 0;
if (const ConfigOption* bottom_opt = mo->config.option("bottom_surface_filament_id"); bottom_opt != nullptr)
obj_bottom_surface_extr = bottom_opt->getInt();
if (obj_bottom_surface_extr == 0)
obj_bottom_surface_extr = obj_internal_solid_extr;
if (obj_bottom_surface_extr != 0)
plate_extruders.push_back(obj_bottom_surface_extr);
else if (glb_bottom_surface_extr != 0)
plate_extruders.push_back(glb_bottom_surface_extr);
}
@@ -1629,9 +1668,16 @@ std::vector<int> PartPlate::get_extruders_under_cli(bool conside_custom_gcode, D
// if 3mf file
int glb_support_intf_extr = full_config.opt_int("support_interface_filament");
int glb_support_extr = full_config.opt_int("support_filament");
int glb_wall_extr = full_config.opt_int("wall_filament");
int glb_sparse_infill_extr = full_config.opt_int("sparse_infill_filament");
int glb_solid_infill_extr = full_config.opt_int("solid_infill_filament");
int glb_outer_wall_extr = full_config.opt_int("outer_wall_filament_id");
int glb_inner_wall_extr = full_config.opt_int("inner_wall_filament_id");
if (glb_outer_wall_extr == 0) glb_outer_wall_extr = glb_inner_wall_extr;
if (glb_inner_wall_extr == 0) glb_inner_wall_extr = glb_outer_wall_extr;
int glb_sparse_infill_extr = full_config.opt_int("sparse_infill_filament_id");
int glb_internal_solid_extr = full_config.opt_int("internal_solid_filament_id");
int glb_top_surface_extr = full_config.opt_int("top_surface_filament_id");
int glb_bottom_surface_extr = full_config.opt_int("bottom_surface_filament_id");
if (glb_top_surface_extr == 0) glb_top_surface_extr = glb_internal_solid_extr;
if (glb_bottom_surface_extr == 0) glb_bottom_surface_extr = glb_internal_solid_extr;
bool glb_support = full_config.opt_bool("enable_support");
glb_support |= full_config.opt_int("raft_layers") > 0;
@@ -1695,17 +1741,30 @@ std::vector<int> PartPlate::get_extruders_under_cli(bool conside_custom_gcode, D
else if (glb_support_extr != 0)
plate_extruders.push_back(glb_support_extr);
int obj_wall_extr = 0;
const ConfigOption* wall_opt = object->config.option("wall_filament");
if (wall_opt != nullptr)
obj_wall_extr = wall_opt->getInt();
if (obj_wall_extr != 0)
plate_extruders.push_back(obj_wall_extr);
else if (glb_wall_extr != 0)
plate_extruders.push_back(glb_wall_extr);
int obj_outer_wall_extr = 0;
if (const ConfigOption* wall_opt = object->config.option("outer_wall_filament_id"); wall_opt != nullptr)
obj_outer_wall_extr = wall_opt->getInt();
if (obj_outer_wall_extr == 0)
if (const ConfigOption* wall_opt = object->config.option("inner_wall_filament_id"); wall_opt != nullptr)
obj_outer_wall_extr = wall_opt->getInt();
if (obj_outer_wall_extr != 0)
plate_extruders.push_back(obj_outer_wall_extr);
else if (glb_outer_wall_extr != 0)
plate_extruders.push_back(glb_outer_wall_extr);
int obj_inner_wall_extr = 0;
if (const ConfigOption* wall_opt = object->config.option("inner_wall_filament_id"); wall_opt != nullptr)
obj_inner_wall_extr = wall_opt->getInt();
if (obj_inner_wall_extr == 0)
if (const ConfigOption* wall_opt = object->config.option("outer_wall_filament_id"); wall_opt != nullptr)
obj_inner_wall_extr = wall_opt->getInt();
if (obj_inner_wall_extr != 0)
plate_extruders.push_back(obj_inner_wall_extr);
else if (glb_inner_wall_extr != 0)
plate_extruders.push_back(glb_inner_wall_extr);
int obj_sparse_infill_extr = 0;
const ConfigOption* sparse_infill_opt = object->config.option("sparse_infill_filament");
const ConfigOption* sparse_infill_opt = object->config.option("sparse_infill_filament_id");
if (sparse_infill_opt != nullptr)
obj_sparse_infill_extr = sparse_infill_opt->getInt();
if (obj_sparse_infill_extr != 0)
@@ -1713,14 +1772,33 @@ std::vector<int> PartPlate::get_extruders_under_cli(bool conside_custom_gcode, D
else if (glb_sparse_infill_extr != 0)
plate_extruders.push_back(glb_sparse_infill_extr);
int obj_solid_infill_extr = 0;
const ConfigOption* solid_infill_opt = object->config.option("solid_infill_filament");
if (solid_infill_opt != nullptr)
obj_solid_infill_extr = solid_infill_opt->getInt();
if (obj_solid_infill_extr != 0)
plate_extruders.push_back(obj_solid_infill_extr);
else if (glb_solid_infill_extr != 0)
plate_extruders.push_back(glb_solid_infill_extr);
int obj_internal_solid_extr = 0;
if (const ConfigOption* solid_opt = object->config.option("internal_solid_filament_id"); solid_opt != nullptr)
obj_internal_solid_extr = solid_opt->getInt();
if (obj_internal_solid_extr != 0)
plate_extruders.push_back(obj_internal_solid_extr);
else if (glb_internal_solid_extr != 0)
plate_extruders.push_back(glb_internal_solid_extr);
int obj_top_surface_extr = 0;
if (const ConfigOption* top_opt = object->config.option("top_surface_filament_id"); top_opt != nullptr)
obj_top_surface_extr = top_opt->getInt();
if (obj_top_surface_extr == 0)
obj_top_surface_extr = obj_internal_solid_extr;
if (obj_top_surface_extr != 0)
plate_extruders.push_back(obj_top_surface_extr);
else if (glb_top_surface_extr != 0)
plate_extruders.push_back(glb_top_surface_extr);
int obj_bottom_surface_extr = 0;
if (const ConfigOption* bottom_opt = object->config.option("bottom_surface_filament_id"); bottom_opt != nullptr)
obj_bottom_surface_extr = bottom_opt->getInt();
if (obj_bottom_surface_extr == 0)
obj_bottom_surface_extr = obj_internal_solid_extr;
if (obj_bottom_surface_extr != 0)
plate_extruders.push_back(obj_bottom_surface_extr);
else if (glb_bottom_surface_extr != 0)
plate_extruders.push_back(glb_bottom_surface_extr);
}
}
+14 -22
View File
@@ -1598,9 +1598,12 @@ Sidebar::Sidebar(Plater *parent)
{
Choice::register_dynamic_list("support_filament", &dynamic_filament_list);
Choice::register_dynamic_list("support_interface_filament", &dynamic_filament_list);
Choice::register_dynamic_list("wall_filament", &dynamic_filament_list);
Choice::register_dynamic_list("sparse_infill_filament", &dynamic_filament_list);
Choice::register_dynamic_list("solid_infill_filament", &dynamic_filament_list);
Choice::register_dynamic_list("outer_wall_filament_id", &dynamic_filament_list);
Choice::register_dynamic_list("inner_wall_filament_id", &dynamic_filament_list);
Choice::register_dynamic_list("sparse_infill_filament_id", &dynamic_filament_list);
Choice::register_dynamic_list("internal_solid_filament_id", &dynamic_filament_list);
Choice::register_dynamic_list("top_surface_filament_id", &dynamic_filament_list);
Choice::register_dynamic_list("bottom_surface_filament_id", &dynamic_filament_list);
Choice::register_dynamic_list("wipe_tower_filament", &dynamic_filament_list);
p->scrolled = new wxPanel(this);
@@ -4871,7 +4874,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
"extruder_colour", "filament_colour", "filament_type", "material_colour", "printable_height", "extruder_printable_height", "printer_model", "printer_technology",
// These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.
"layer_height", "initial_layer_print_height", "min_layer_height", "max_layer_height",
"wall_loops", "wall_filament", "sparse_infill_density", "sparse_infill_filament", "top_shell_layers",
"wall_loops", "outer_wall_filament_id", "inner_wall_filament_id", "sparse_infill_density", "sparse_infill_filament_id", "top_shell_layers",
"enable_support", "support_filament", "support_interface_filament",
"support_top_z_distance", "support_bottom_z_distance", "raft_layers",
"wipe_tower_rotation_angle", "wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower_extra_flow", "wipe_tower_max_purge_speed",
@@ -6153,22 +6156,9 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
}
}
if (load_config && !config_loaded.empty() &&
(en_3mf_file_type == En3mfType::From_BBS || en_3mf_file_type == En3mfType::From_Orca) &&
file_version < Semver("2.4.0-dev")) {
int converted_count = ConfigMigrations::migrate_legacy_feature_filament_defaults(config_loaded);
for (ModelObject *model_object : model.objects) {
converted_count += ConfigMigrations::migrate_legacy_feature_filament_defaults(model_object->config);
for (ModelVolume *model_volume : model_object->volumes)
converted_count += ConfigMigrations::migrate_legacy_feature_filament_defaults(model_volume->config);
}
if (converted_count > 0) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << " "
<< boost::format("old 3mf version %1%, migrated %2% feature filament selections from 1 to 0 (Default)")
% file_version.to_string() % converted_count;
}
}
// ORCA: legacy feature-filament default migration (1 -> 0) is now handled
// uniformly in PrintConfigDef::handle_legacy() via the old->new key rename
// (wall_filament -> wall_filament_id, etc.), which also covers saved presets.
// plate data
if (plate_data.size() > 0) {
@@ -16669,8 +16659,10 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
update_scheduled = true;
}
// Orca: update when *_filament changed
else if (opt_key == "support_interface_filament" || opt_key == "support_filament" || opt_key == "wall_filament" ||
opt_key == "sparse_infill_filament" || opt_key == "solid_infill_filament") {
else if (opt_key == "support_interface_filament" || opt_key == "support_filament" ||
opt_key == "outer_wall_filament_id" || opt_key == "inner_wall_filament_id" ||
opt_key == "sparse_infill_filament_id" || opt_key == "internal_solid_filament_id" ||
opt_key == "top_surface_filament_id" || opt_key == "bottom_surface_filament_id") {
update_scheduled = true;
}
}
+6 -3
View File
@@ -128,9 +128,12 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle
auto feature_extruder_active = [idx_extruder, num_extruders](int i) {
return i <= 0 || i > num_extruders || idx_extruder == -1 || idx_extruder == i - 1;
};
bool perimeter_extruder_active = feature_extruder_active(print_config.opt_int("wall_filament"));
bool infill_extruder_active = feature_extruder_active(print_config.opt_int("sparse_infill_filament"));
bool solid_infill_extruder_active = feature_extruder_active(print_config.opt_int("solid_infill_filament"));
bool perimeter_extruder_active = feature_extruder_active(print_config.opt_int("outer_wall_filament_id"))
&& feature_extruder_active(print_config.opt_int("inner_wall_filament_id"));
bool infill_extruder_active = feature_extruder_active(print_config.opt_int("sparse_infill_filament_id"));
bool solid_infill_extruder_active = feature_extruder_active(print_config.opt_int("internal_solid_filament_id"))
&& feature_extruder_active(print_config.opt_int("top_surface_filament_id"))
&& feature_extruder_active(print_config.opt_int("bottom_surface_filament_id"));
bool support_material_extruder_active = feature_extruder_active(print_config.opt_int("support_filament"));
bool support_material_interface_extruder_active = feature_extruder_active(print_config.opt_int("support_interface_filament"));
+6 -3
View File
@@ -2667,9 +2667,12 @@ void TabPrint::build()
optgroup->append_single_option_line("single_extruder_multi_material_priming", "multimaterial_settings_prime_tower");
optgroup = page->new_optgroup(L("Filament for Features"), L"param_filament_for_features");
optgroup->append_single_option_line("wall_filament", "multimaterial_settings_filament_for_features#walls");
optgroup->append_single_option_line("sparse_infill_filament", "multimaterial_settings_filament_for_features#infill");
optgroup->append_single_option_line("solid_infill_filament", "multimaterial_settings_filament_for_features#solid-infill");
optgroup->append_single_option_line("outer_wall_filament_id", "multimaterial_settings_filament_for_features#walls");
optgroup->append_single_option_line("inner_wall_filament_id", "multimaterial_settings_filament_for_features#walls");
optgroup->append_single_option_line("sparse_infill_filament_id", "multimaterial_settings_filament_for_features#infill");
optgroup->append_single_option_line("internal_solid_filament_id", "multimaterial_settings_filament_for_features#solid-infill");
optgroup->append_single_option_line("top_surface_filament_id", "multimaterial_settings_filament_for_features#solid-infill");
optgroup->append_single_option_line("bottom_surface_filament_id", "multimaterial_settings_filament_for_features#solid-infill");
optgroup->append_single_option_line("wipe_tower_filament", "multimaterial_settings_filament_for_features#wipe-tower");
optgroup = page->new_optgroup(L("Ooze prevention"), L"param_ooze_prevention");