Fix #119055: GPv3: Set end caps correctly with hard eraser
The hard eraser changes end caps to "flat" when cutting strokes. This requires detecting when the start or end points of a stroke have been cut. The previous method relied on checking the next curve's start point for cuts to determine end point cuts, but this only holds true for cutting strokes in the middle. When only the start point is cut the preceding curve should not be affected. The new test uses local properties of the `PointTransferData` to detect unchanged source curve end points, instead of doing a look-ahead for the next curve. This works using the source point indices, which are inverted for end points. Combined with checking for the `is_cut` flag this gives a reliable answer to when a stroke end point is cut. Pull Request: https://projects.blender.org/blender/blender/pulls/119151
This commit is contained in:
@@ -382,6 +382,17 @@ struct EraseOperationExecutor {
|
||||
float factor;
|
||||
bool is_src_point;
|
||||
bool is_cut;
|
||||
|
||||
/**
|
||||
* Source point is the last of the curve.
|
||||
*/
|
||||
bool is_src_end_point() const
|
||||
{
|
||||
/* The src_next_point index increments for all points except the last, where it is set to the
|
||||
* first point index. This can be used to detect the curve end from the source index alone.
|
||||
*/
|
||||
return is_src_point && src_point >= src_next_point;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -547,18 +558,16 @@ struct EraseOperationExecutor {
|
||||
threading::parallel_for(dst.curves_range(), 4096, [&](const IndexRange dst_curves) {
|
||||
for (const int dst_curve : dst_curves) {
|
||||
const IndexRange dst_curve_points = dst_points_by_curve[dst_curve];
|
||||
if (dst_transfer_data[dst_curve_points.first()].is_cut) {
|
||||
const PointTransferData &start_point_transfer =
|
||||
dst_transfer_data[dst_curve_points.first()];
|
||||
const PointTransferData &end_point_transfer = dst_transfer_data[dst_curve_points.last()];
|
||||
|
||||
if (start_point_transfer.is_cut) {
|
||||
dst_start_caps.span[dst_curve] = GP_STROKE_CAP_TYPE_FLAT;
|
||||
}
|
||||
|
||||
if (dst_curve == dst_curves.last()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const PointTransferData &next_point_transfer =
|
||||
dst_transfer_data[dst_points_by_curve[dst_curve + 1].first()];
|
||||
|
||||
if (next_point_transfer.is_cut) {
|
||||
/* The is_cut flag does not work for end points, but any end point that isn't the source
|
||||
* point must also be a cut. */
|
||||
if (!end_point_transfer.is_src_end_point()) {
|
||||
dst_end_caps.span[dst_curve] = GP_STROKE_CAP_TYPE_FLAT;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user