From 32be07845f750f81023815bb95cbd3cb08e8d7a6 Mon Sep 17 00:00:00 2001 From: Falk David Date: Mon, 26 Jun 2023 11:21:16 +0200 Subject: [PATCH] Curves: Mask function for end points This essentially replaces the `ed::curves::select_ends` function by using a new masking function (`ed::curves::end_points`) and manipulating the selection attribute directly in the operators. Pull Request: https://projects.blender.org/blender/blender/pulls/109293 --- source/blender/editors/curves/CMakeLists.txt | 1 + .../editors/curves/intern/curves_masks.cc | 35 +++++++++++++++++++ .../editors/curves/intern/curves_ops.cc | 20 ++++++++++- .../editors/curves/intern/curves_selection.cc | 28 --------------- .../intern/grease_pencil_select.cc | 21 ++++++++++- source/blender/editors/include/ED_curves.h | 26 +++++++++----- 6 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 source/blender/editors/curves/intern/curves_masks.cc diff --git a/source/blender/editors/curves/CMakeLists.txt b/source/blender/editors/curves/CMakeLists.txt index 6774f8733d2..893b1f82c4c 100644 --- a/source/blender/editors/curves/CMakeLists.txt +++ b/source/blender/editors/curves/CMakeLists.txt @@ -26,6 +26,7 @@ set(SRC intern/curves_add.cc intern/curves_data.cc intern/curves_edit.cc + intern/curves_masks.cc intern/curves_ops.cc intern/curves_selection.cc intern/curves_undo.cc diff --git a/source/blender/editors/curves/intern/curves_masks.cc b/source/blender/editors/curves/intern/curves_masks.cc new file mode 100644 index 00000000000..9392f28b3d0 --- /dev/null +++ b/source/blender/editors/curves/intern/curves_masks.cc @@ -0,0 +1,35 @@ +/* SPDX-FileCopyrightText: 2023 Blender Foundation + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup edcurves + */ + +#include "BKE_curves.hh" + +#include "ED_curves.h" + +namespace blender::ed::curves { + +IndexMask end_points(const bke::CurvesGeometry &curves, + const int amount_start, + const int amount_end, + const bool inverted, + IndexMaskMemory &memory) +{ + const OffsetIndices points_by_curve = curves.points_by_curve(); + + Array end_points(curves.points_num(), inverted ? false : true); + threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) { + for (const int curve_i : range) { + end_points.as_mutable_span() + .slice(points_by_curve[curve_i].drop_front(amount_start).drop_back(amount_end)) + .fill(inverted ? true : false); + } + }); + + return IndexMask::from_bools(end_points, memory); +} + +} // namespace blender::ed::curves diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc index 401e85192b9..b152e011285 100644 --- a/source/blender/editors/curves/intern/curves_ops.cc +++ b/source/blender/editors/curves/intern/curves_ops.cc @@ -948,7 +948,25 @@ static int select_ends_exec(bContext *C, wmOperator *op) for (Curves *curves_id : unique_curves) { CurvesGeometry &curves = curves_id->geometry.wrap(); - select_ends(curves, amount_start, amount_end); + + IndexMaskMemory memory; + const IndexMask inverted_end_points_mask = end_points( + curves, amount_start, amount_end, true, memory); + + const bool was_anything_selected = has_anything_selected(curves); + bke::GSpanAttributeWriter selection = ensure_selection_attribute( + curves, ATTR_DOMAIN_POINT, CD_PROP_BOOL); + if (!was_anything_selected) { + fill_selection_true(selection.span); + } + + if (selection.span.type().is()) { + index_mask::masked_fill(selection.span.typed(), false, inverted_end_points_mask); + } + if (selection.span.type().is()) { + index_mask::masked_fill(selection.span.typed(), 0.0f, inverted_end_points_mask); + } + selection.finish(); /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic * attribute for now. */ diff --git a/source/blender/editors/curves/intern/curves_selection.cc b/source/blender/editors/curves/intern/curves_selection.cc index 01760b30fed..5b7bba6add4 100644 --- a/source/blender/editors/curves/intern/curves_selection.cc +++ b/source/blender/editors/curves/intern/curves_selection.cc @@ -227,34 +227,6 @@ void select_all(bke::CurvesGeometry &curves, const eAttrDomain selection_domain, } } -void select_ends(bke::CurvesGeometry &curves, int amount_start, int amount_end) -{ - const bool was_anything_selected = has_anything_selected(curves); - const OffsetIndices points_by_curve = curves.points_by_curve(); - bke::GSpanAttributeWriter selection = ensure_selection_attribute( - curves, ATTR_DOMAIN_POINT, CD_PROP_BOOL); - if (!was_anything_selected) { - fill_selection_true(selection.span); - } - selection.span.type().to_static_type_tag([&](auto type_tag) { - using T = typename decltype(type_tag)::type; - if constexpr (std::is_void_v) { - BLI_assert_unreachable(); - } - else { - MutableSpan selection_typed = selection.span.typed(); - threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) { - for (const int curve_i : range) { - selection_typed - .slice(points_by_curve[curve_i].drop_front(amount_start).drop_back(amount_end)) - .fill(T(0)); - } - }); - } - }); - selection.finish(); -} - void select_linked(bke::CurvesGeometry &curves) { const OffsetIndices points_by_curve = curves.points_by_curve(); diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc index 60132eb0b3f..725856a2b64 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc @@ -243,7 +243,26 @@ static int select_ends_exec(bContext *C, wmOperator *op) grease_pencil.foreach_editable_drawing( scene->r.cfra, [&](int /*drawing_index*/, GreasePencilDrawing &drawing) { - blender::ed::curves::select_ends(drawing.geometry.wrap(), amount_start, amount_end); + bke::CurvesGeometry &curves = drawing.geometry.wrap(); + + IndexMaskMemory memory; + const IndexMask inverted_end_points_mask = ed::curves::end_points( + curves, amount_start, amount_end, true, memory); + + const bool was_anything_selected = ed::curves::has_anything_selected(curves); + bke::GSpanAttributeWriter selection = ed::curves::ensure_selection_attribute( + curves, ATTR_DOMAIN_POINT, CD_PROP_BOOL); + if (!was_anything_selected) { + ed::curves::fill_selection_true(selection.span); + } + + if (selection.span.type().is()) { + index_mask::masked_fill(selection.span.typed(), false, inverted_end_points_mask); + } + if (selection.span.type().is()) { + index_mask::masked_fill(selection.span.typed(), 0.0f, inverted_end_points_mask); + } + selection.finish(); }); /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic diff --git a/source/blender/editors/include/ED_curves.h b/source/blender/editors/include/ED_curves.h index 8d3b2140fdc..12d836fa7ab 100644 --- a/source/blender/editors/include/ED_curves.h +++ b/source/blender/editors/include/ED_curves.h @@ -89,6 +89,24 @@ bool curves_poll(bContext *C); /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Mask Functions + * \{ */ + +/** + * Return a mask of all the end points in the curves. + * \param amount_start: The amount of points to mask from the front. + * \param amount_end: The amount of points to mask from the back. + * \param inverted: Invert the resulting mask. + */ +IndexMask end_points(const bke::CurvesGeometry &curves, + int amount_start, + int amount_end, + bool inverted, + IndexMaskMemory &memory); + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Selection * @@ -147,14 +165,6 @@ void apply_selection_operation_at_index(GMutableSpan selection, int index, eSele */ void select_all(bke::CurvesGeometry &curves, eAttrDomain selection_domain, int action); -/** - * Select the ends (front or back) of all the curves. - * - * \param amount_start: The amount of points to select from the front. - * \param amount_end: The amount of points to select from the back. - */ -void select_ends(bke::CurvesGeometry &curves, int amount_start, int amount_end); - /** * Select the points of all curves that have at least one point selected. */