[Bf-blender-cvs] [70ca15670d9] master: Curves: Edit mode selection operators

Falk David noreply at git.blender.org
Fri Jan 20 16:41:12 CET 2023


Commit: 70ca15670d9f6d7179d1fe150939582c91174c29
Author: Falk David
Date:   Fri Jan 20 16:40:51 2023 +0100
Branches: master
https://developer.blender.org/rB70ca15670d9f6d7179d1fe150939582c91174c29

Curves: Edit mode selection operators

This adds the following operators to edit mode:
 - `select_all`
 - `select_random`
 - `select_end`

Differential Revision: https://developer.blender.org/D17047

===================================================================

M	release/scripts/modules/bl_keymap_utils/keymap_hierarchy.py
M	release/scripts/presets/keyconfig/keymap_data/blender_default.py
M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/editors/curves/intern/curves_ops.cc
M	source/blender/editors/curves/intern/curves_selection.cc
M	source/blender/editors/include/ED_curves.h
M	source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
M	source/blender/editors/space_api/spacetypes.c
M	source/blender/editors/space_view3d/space_view3d.cc

===================================================================

diff --git a/release/scripts/modules/bl_keymap_utils/keymap_hierarchy.py b/release/scripts/modules/bl_keymap_utils/keymap_hierarchy.py
index 7172d7809f2..f183877749c 100644
--- a/release/scripts/modules/bl_keymap_utils/keymap_hierarchy.py
+++ b/release/scripts/modules/bl_keymap_utils/keymap_hierarchy.py
@@ -55,6 +55,7 @@ _km_hierarchy = [
         ('Curve', 'EMPTY', 'WINDOW', [
             _km_expand_from_toolsystem('VIEW_3D', 'EDIT_CURVE'),
         ]),
+        ('Curves', 'EMPTY', 'WINDOW', []),
         ('Armature', 'EMPTY', 'WINDOW', [
             _km_expand_from_toolsystem('VIEW_3D', 'EDIT_ARMATURE'),
         ]),
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 19093e51ec5..4149377581c 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -5615,6 +5615,14 @@ def km_curves(params):
         {"items": items},
     )
 
+    items.extend([
+        ("curves.set_selection_domain", {"type": 'ONE', "value": 'PRESS'}, {"properties": [("domain", 'POINT')]}),
+        ("curves.set_selection_domain", {"type": 'TWO', "value": 'PRESS'}, {"properties": [("domain", 'CURVE')]}),
+        ("curves.disable_selection", {"type": 'ONE', "value": 'PRESS', "alt": True}, None),
+        ("curves.disable_selection", {"type": 'TWO', "value": 'PRESS', "alt": True}, None),
+        *_template_items_select_actions(params, "curves.select_all"),
+    ])
+
     return keymap
 
 
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 3bb009dd2ad..938399485d3 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -718,7 +718,7 @@ class VIEW3D_HT_header(Header):
             if object_mode == 'PARTICLE_EDIT':
                 row = layout.row()
                 row.prop(tool_settings.particle_edit, "select_mode", text="", expand=True)
-            elif object_mode == 'SCULPT_CURVES' and obj.type == 'CURVES':
+            elif object_mode in {'EDIT', 'SCULPT_CURVES'} and obj.type == 'CURVES':
                 curves = obj.data
 
                 row = layout.row(align=True)
@@ -2044,7 +2044,13 @@ class VIEW3D_MT_select_edit_curves(Menu):
     bl_label = "Select"
 
     def draw(self, _context):
-        pass
+        layout = self.layout
+
+        layout.operator("curves.select_all", text="All").action = 'SELECT'
+        layout.operator("curves.select_all", text="None").action = 'DESELECT'
+        layout.operator("curves.select_all", text="Invert").action = 'INVERT'
+        layout.operator("curves.select_random", text="Random")
+        layout.operator("curves.select_end", text="Endpoints")
 
 
 class VIEW3D_MT_select_sculpt_curves(Menu):
@@ -2057,7 +2063,7 @@ class VIEW3D_MT_select_sculpt_curves(Menu):
         layout.operator("curves.select_all", text="None").action = 'DESELECT'
         layout.operator("curves.select_all", text="Invert").action = 'INVERT'
         layout.operator("sculpt_curves.select_random", text="Random")
-        layout.operator("sculpt_curves.select_end", text="Endpoints")
+        layout.operator("curves.select_end", text="Endpoints")
         layout.operator("sculpt_curves.select_grow", text="Grow")
 
 
diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc
index 24aa362b973..d0a68774c71 100644
--- a/source/blender/editors/curves/intern/curves_ops.cc
+++ b/source/blender/editors/curves/intern/curves_ops.cc
@@ -7,7 +7,10 @@
 #include <atomic>
 
 #include "BLI_array_utils.hh"
+#include "BLI_devirtualize_parameters.hh"
 #include "BLI_index_mask_ops.hh"
+#include "BLI_kdtree.h"
+#include "BLI_rand.hh"
 #include "BLI_utildefines.h"
 #include "BLI_vector_set.hh"
 
@@ -15,6 +18,7 @@
 #include "ED_object.h"
 #include "ED_screen.h"
 #include "ED_select_utils.h"
+#include "ED_view3d.h"
 
 #include "WM_api.h"
 
@@ -48,6 +52,9 @@
 #include "RNA_enum_types.h"
 #include "RNA_prototypes.h"
 
+#include "UI_interface.h"
+#include "UI_resources.h"
+
 #include "GEO_reverse_uv_sampler.hh"
 
 /**
@@ -820,113 +827,133 @@ static void CURVES_OT_set_selection_domain(wmOperatorType *ot)
   RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE));
 }
 
-static bool contains(const VArray<bool> &varray, const bool value)
+static bool has_anything_selected(const Span<Curves *> curves_ids)
+{
+  return std::any_of(curves_ids.begin(), curves_ids.end(), [](const Curves *curves_id) {
+    return has_anything_selected(CurvesGeometry::wrap(curves_id->geometry));
+  });
+}
+
+static int select_all_exec(bContext *C, wmOperator *op)
 {
-  const CommonVArrayInfo info = varray.common_info();
-  if (info.type == CommonVArrayInfo::Type::Single) {
-    return *static_cast<const bool *>(info.data) == value;
+  int action = RNA_enum_get(op->ptr, "action");
+
+  VectorSet<Curves *> unique_curves = get_unique_editable_curves(*C);
+
+  if (action == SEL_TOGGLE) {
+    action = has_anything_selected(unique_curves) ? SEL_DESELECT : SEL_SELECT;
   }
-  if (info.type == CommonVArrayInfo::Type::Span) {
-    const Span<bool> span(static_cast<const bool *>(info.data), varray.size());
-    return threading::parallel_reduce(
-        span.index_range(),
-        4096,
-        false,
-        [&](const IndexRange range, const bool init) {
-          return init || span.slice(range).contains(value);
-        },
-        [&](const bool a, const bool b) { return a || b; });
+
+  for (Curves *curves_id : unique_curves) {
+    /* (De)select all the curves. */
+    select_all(CurvesGeometry::wrap(curves_id->geometry),
+               eAttrDomain(curves_id->selection_domain),
+               action);
+
+    /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
+     * attribute for now. */
+    DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY);
+    WM_event_add_notifier(C, NC_GEOM | ND_DATA, curves_id);
   }
-  return threading::parallel_reduce(
-      varray.index_range(),
-      2048,
-      false,
-      [&](const IndexRange range, const bool init) {
-        if (init) {
-          return init;
-        }
-        /* Alternatively, this could use #materialize to retrieve many values at once. */
-        for (const int64_t i : range) {
-          if (varray[i] == value) {
-            return true;
-          }
-        }
-        return false;
-      },
-      [&](const bool a, const bool b) { return a || b; });
+
+  return OPERATOR_FINISHED;
 }
 
-bool has_anything_selected(const Curves &curves_id)
+static void CURVES_OT_select_all(wmOperatorType *ot)
 {
-  const CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
-  const VArray<bool> selection = curves.attributes().lookup<bool>(".selection");
-  return !selection || contains(selection, true);
+  ot->name = "(De)select All";
+  ot->idname = "CURVES_OT_select_all";
+  ot->description = "(De)select all control points";
+
+  ot->exec = select_all_exec;
+  ot->poll = editable_curves_poll;
+
+  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+  WM_operator_properties_select_all(ot);
 }
 
-static bool has_anything_selected(const Span<Curves *> curves_ids)
+static int select_random_exec(bContext *C, wmOperator *op)
 {
-  return std::any_of(curves_ids.begin(), curves_ids.end(), [](const Curves *curves_id) {
-    return has_anything_selected(*curves_id);
-  });
+  VectorSet<Curves *> unique_curves = curves::get_unique_editable_curves(*C);
+
+  const int seed = RNA_int_get(op->ptr, "seed");
+  const float probability = RNA_float_get(op->ptr, "probability");
+
+  for (Curves *curves_id : unique_curves) {
+    CurvesGeometry &curves = CurvesGeometry::wrap(curves_id->geometry);
+    select_random(curves, eAttrDomain(curves_id->selection_domain), uint32_t(seed), probability);
+
+    /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
+     * attribute for now. */
+    DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY);
+    WM_event_add_notifier(C, NC_GEOM | ND_DATA, curves_id);
+  }
+  return OPERATOR_FINISHED;
 }
 
-namespace select_all {
+static void select_random_ui(bContext * /*C*/, wmOperator *op)
+{
+  uiLayout *layout = op->layout;
 
-static void invert_selection(MutableSpan<float> selection)
+  uiItemR(layout, op->ptr, "seed", 0, nullptr, ICON_NONE);
+  uiItemR(layout, op->ptr, "probability", UI_ITEM_R_SLIDER, "Probability", ICON_NONE);
+}
+
+static void CURVES_OT_select_random(wmOperatorType *ot)
 {
-  threading::parallel_for(selection.index_range(), 2048, [&](IndexRange range) {
-    for (const int i : range) {
-      selection[i] = 1.0f - selection[i];
-    }
-  });
+  ot->name = "Select Random";
+  ot->idname = __func__;
+  ot->description = "Randomizes existing selection or create new random selection";
+
+  ot->exec = select_random_exec;
+  ot->poll = curves::editable_curves_poll;
+  ot->ui = select_random_ui;
+
+  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+  RNA_def_int(ot->srna,
+              "seed",
+              0,
+              INT32_MIN,
+              INT32_MAX,
+              "Seed",
+              "Source of randomness",
+              INT32_MIN,
+              INT32_MAX);
+  RNA_def_float(ot->srna,
+                "probability",
+                0.5f,
+                0.0f,
+                1.0f,
+                "Probability",
+                "Chance of every point or curve being included in the selection",
+                0.0f,
+                1.0f);
 }
 
-static void invert_selection(GMutableSpan selection)
+static bool select_end_poll(bContext *C)
 {
-  if (selection.type().is<bool>()) {
-    array_utils::invert_booleans(selection.typed<bool>());
+  if (!curves::editable_curves_poll(C)) {
+    return false;
   }
-  else if (selection.type().is<float>()) {
-    invert_selection(selection.typed<float>());
+  const Curves *curves_id = static_cast<const Curves *>(CTX_data_active_object(C)->data);
+  if (curves_id->selection_domain != ATTR_DOMAIN_POINT) {
+    CTX_wm_operator_poll_msg_set(C, "Only available in point selection mode");
+    return false

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list