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 09:45:43 -03:00
committed by GitHub
parent 6667266b44
commit ea35b9ce68
115 changed files with 1168 additions and 605 deletions

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.

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;

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;