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
This commit is contained in:
@@ -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
|
||||
|
||||
35
source/blender/editors/curves/intern/curves_masks.cc
Normal file
35
source/blender/editors/curves/intern/curves_masks.cc
Normal file
@@ -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<bool> 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
|
||||
@@ -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<bool>()) {
|
||||
index_mask::masked_fill(selection.span.typed<bool>(), false, inverted_end_points_mask);
|
||||
}
|
||||
if (selection.span.type().is<float>()) {
|
||||
index_mask::masked_fill(selection.span.typed<float>(), 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. */
|
||||
|
||||
@@ -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<bool, float>([&](auto type_tag) {
|
||||
using T = typename decltype(type_tag)::type;
|
||||
if constexpr (std::is_void_v<T>) {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
else {
|
||||
MutableSpan<T> selection_typed = selection.span.typed<T>();
|
||||
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();
|
||||
|
||||
@@ -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<bool>()) {
|
||||
index_mask::masked_fill(selection.span.typed<bool>(), false, inverted_end_points_mask);
|
||||
}
|
||||
if (selection.span.type().is<float>()) {
|
||||
index_mask::masked_fill(selection.span.typed<float>(), 0.0f, inverted_end_points_mask);
|
||||
}
|
||||
selection.finish();
|
||||
});
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user