Refactor skirt/brim + bugfixes related to them (#14333)

Refactor skirt and brim ownership and emission flow

Refactor skirt and brim generation around a common object/group
ownership model.

Skirts and brims are now emitted as a coordinated preamble
(skirt -> brim -> object) instead of being generated and emitted
through multiple independent code paths.

Changes:
- Fix repeated skirt emission caused by the previous skirt state
  tracking logic.
- Restore local skirt/brim ordering for per-object skirts in
  By Layer mode.
- Emit brims together with their owning object or object group.
- Handle combined brims independently from skirt grouping.
- Handle draft shields through the same ownership model as skirts.
- Fix draft shield generation when skirt height is zero.
- Generate draft shields after brim geometry is known, preventing
  draft shields from overlapping brims.
- Reject unsafe grouped per-object skirt configurations in
  By Object mode.
- Remove legacy skirt emission paths and state-management
  workarounds.

Support brim generation remains unchanged.

Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
Kiss Lorand
2026-06-24 15:48:31 +08:00
committed by GitHub
co-authored by SoftFever
parent 4c3e30144d
commit 045179150f
6 changed files with 282 additions and 187 deletions
+26 -12
View File
@@ -833,8 +833,7 @@ Polygons tryExPolygonOffset(const ExPolygons& islandAreaEx, const Print& print)
}
return loops;
}
//BBS: a function creates the ExtrusionEntityCollection from the brim area defined by ExPolygons
ExtrusionEntityCollection makeBrimInfill(const ExPolygons& singleBrimArea, const Print& print, const Polygons& islands_area) {
static ExtrusionEntityCollection makeBrimInfillImpl(const ExPolygons& singleBrimArea, const Print& print, const Polygons& islands_area, bool apply_plate_offset) {
Polygons loops = tryExPolygonOffset(singleBrimArea, print);
Flow flow = print.brim_flow();
loops = union_pt_chained_outside_in(loops);
@@ -864,16 +863,29 @@ ExtrusionEntityCollection makeBrimInfill(const ExPolygons& singleBrimArea, const
optimize_polylines_by_reversing(&all_loops);
all_loops = connect_brim_lines(std::move(all_loops), offset(singleBrimArea, float(SCALED_EPSILON)), float(flow.scaled_spacing()) * 2.f);
//BBS: finally apply the plate offset which may very large
auto plate_offset = print.get_plate_origin();
Point scaled_plate_offset = Point(scaled(plate_offset.x()), scaled(plate_offset.y()));
for (Polyline& one_loop : all_loops)
one_loop.translate(scaled_plate_offset);
if (apply_plate_offset) {
//BBS: finally apply the plate offset which may very large
auto plate_offset = print.get_plate_origin();
Point scaled_plate_offset = Point(scaled(plate_offset.x()), scaled(plate_offset.y()));
for (Polyline& one_loop : all_loops)
one_loop.translate(scaled_plate_offset);
}
extrusion_entities_append_loops_and_paths(brim.entities, std::move(all_loops), erBrim, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height()));
return brim;
}
//BBS: a function creates the ExtrusionEntityCollection from the brim area defined by ExPolygons
ExtrusionEntityCollection makeBrimInfill(const ExPolygons& singleBrimArea, const Print& print, const Polygons& islands_area)
{
return makeBrimInfillImpl(singleBrimArea, print, islands_area, true);
}
ExtrusionEntityCollection makeBrimInfillFromPlateCoordinates(const ExPolygons& singleBrimArea, const Print& print, const Polygons& islands_area)
{
return makeBrimInfillImpl(singleBrimArea, print, islands_area, false);
}
//BBS: an overload of the orignal brim generator that generates the brim by obj and by extruders
void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_area,
std::map<ObjectID, ExtrusionEntityCollection>& brimMap,
@@ -943,11 +955,13 @@ void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_
if (supportBrimAreasOut != nullptr)
*supportBrimAreasOut = translate_area_map(supportBrimAreaMap);
const bool combine_brims = print.config().combine_brims.value;
const bool is_by_object = (print.config().print_sequence == PrintSequence::ByObject);
const bool can_combine_brims = combine_brims && !is_by_object;
const bool has_per_object_skirt_or_shield = print.config().skirt_type == stPerObject &&
(print.has_skirt() || print.has_infinite_skirt());
const bool combine_brims = print.config().combine_brims.value &&
!has_per_object_skirt_or_shield &&
print.config().print_sequence != PrintSequence::ByObject;
if (!can_combine_brims) {
if (!combine_brims) {
// Orca: Generate brims separately when brims cannot be combined.
for (auto iter = brimAreaMap.begin(); iter != brimAreaMap.end(); ++iter) {
if (!iter->second.empty()) {
@@ -960,7 +974,7 @@ void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_
};
}
} else {
// Orca: Unified brim mode (non-sequential printing)
// Orca: Unified brim mode.
ExPolygons all_brims_merged;
std::vector<ObjectID> brim_object_ids;