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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs