Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-05-31 20:00:24 +0300
committerHans Goudey <h.goudey@me.com>2022-05-31 20:00:24 +0300
commita1830859fa98d529a2eae709b2557a91f1bbe9e7 (patch)
tree7ae959d2351cfbabe0f28a6077096b197b3911c1 /source/blender/editors/sculpt_paint/curves_sculpt_selection.cc
parent96f20ddc1e84e0f5036ea1bdda8381f037069f77 (diff)
Curves: Add soft selection in sculpt mode
This commit adds a float selection to curve control points or curves, a sculpt tool to paint the selection, and uses the selection influence in the existing sculpt brushes. The selection is the inverse of the "mask" from mesh sculpt mode currently. That change is described in more detail here: T97903 Since some sculpt tools are really "per curve" tools, they use the average point selection of all of their points. The delete brush considers a curve selected if any of its points have a non-zero selection. There is a new option to choose the selection domain, which affects how painting the selection works. You can also turn the selection off by clicking on the active domain. Sculpt brushes can be faster when the selection is small, because finding selected curves or points is generally faster than the existing brush intersection and distance checks. The main limitation currently is that we can't see the selection in the viewport by default. For now, to see the selection one has to add a simple material to the curves object as shown in the differential revision. And one has to switch to Material Preview in the 3d view. Differential Revision: https://developer.blender.org/D14934
Diffstat (limited to 'source/blender/editors/sculpt_paint/curves_sculpt_selection.cc')
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_selection.cc107
1 files changed, 107 insertions, 0 deletions
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_selection.cc b/source/blender/editors/sculpt_paint/curves_sculpt_selection.cc
new file mode 100644
index 00000000000..9a14f0cfef0
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_selection.cc
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "BLI_index_mask_ops.hh"
+
+#include "BKE_curves.hh"
+
+#include "curves_sculpt_intern.hh"
+
+namespace blender::ed::sculpt_paint {
+
+static VArray<float> get_curves_selection(const CurvesGeometry &curves,
+ const AttributeDomain domain)
+{
+ switch (domain) {
+ case ATTR_DOMAIN_CURVE:
+ return curves.selection_curve_float();
+ case ATTR_DOMAIN_POINT:
+ return curves.adapt_domain(
+ curves.selection_point_float(), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
+ default:
+ BLI_assert_unreachable();
+ return {};
+ }
+}
+
+VArray<float> get_curves_selection(const Curves &curves_id)
+{
+ if (!(curves_id.flag & CV_SCULPT_SELECTION_ENABLED)) {
+ return VArray<float>::ForSingle(1.0f, CurvesGeometry::wrap(curves_id.geometry).curves_num());
+ }
+ return get_curves_selection(CurvesGeometry::wrap(curves_id.geometry),
+ AttributeDomain(curves_id.selection_domain));
+}
+
+static VArray<float> get_point_selection(const CurvesGeometry &curves,
+ const AttributeDomain domain)
+{
+ switch (domain) {
+ case ATTR_DOMAIN_CURVE:
+ return curves.adapt_domain(
+ curves.selection_curve_float(), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT);
+ case ATTR_DOMAIN_POINT:
+ return curves.selection_point_float();
+ default:
+ BLI_assert_unreachable();
+ return {};
+ }
+}
+
+VArray<float> get_point_selection(const Curves &curves_id)
+{
+ if (!(curves_id.flag & CV_SCULPT_SELECTION_ENABLED)) {
+ return VArray<float>::ForSingle(1.0f, CurvesGeometry::wrap(curves_id.geometry).points_num());
+ }
+ return get_point_selection(CurvesGeometry::wrap(curves_id.geometry),
+ AttributeDomain(curves_id.selection_domain));
+}
+
+static IndexMask retrieve_selected_curves(const CurvesGeometry &curves,
+ const AttributeDomain domain,
+ Vector<int64_t> &r_indices)
+{
+ switch (domain) {
+ case ATTR_DOMAIN_POINT: {
+ const VArray<float> selection = curves.selection_point_float();
+ if (selection.is_single()) {
+ return selection.get_internal_single() == 0.0f ? IndexMask(0) :
+ IndexMask(curves.curves_num());
+ }
+ return index_mask_ops::find_indices_based_on_predicate(
+ curves.curves_range(), 512, r_indices, [&](const int curve_i) {
+ for (const int i : curves.points_for_curve(curve_i)) {
+ if (selection[i] > 0.0f) {
+ return true;
+ }
+ }
+ return false;
+ });
+ }
+ case ATTR_DOMAIN_CURVE: {
+ const VArray<float> selection = curves.selection_curve_float();
+ if (selection.is_single()) {
+ return selection.get_internal_single() == 0.0f ? IndexMask(0) :
+ IndexMask(curves.curves_num());
+ }
+ return index_mask_ops::find_indices_based_on_predicate(
+ curves.curves_range(), 2048, r_indices, [&](const int i) {
+ return selection[i] > 0.0f;
+ });
+ }
+ default:
+ BLI_assert_unreachable();
+ return {};
+ }
+}
+
+IndexMask retrieve_selected_curves(const Curves &curves_id, Vector<int64_t> &r_indices)
+{
+ if (!(curves_id.flag & CV_SCULPT_SELECTION_ENABLED)) {
+ return CurvesGeometry::wrap(curves_id.geometry).curves_range();
+ }
+ return retrieve_selected_curves(CurvesGeometry::wrap(curves_id.geometry),
+ AttributeDomain(curves_id.selection_domain),
+ r_indices);
+}
+
+} // namespace blender::ed::sculpt_paint