From 23cd299ba7e039e25a2b2f7107728ed010846808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Tue, 24 Sep 2024 16:27:06 +0200 Subject: [PATCH] GPv3: Selection support in Sculpt mode Supporting selection operators and overlays in sculpt mode is necessary to support masking operations. This enables selection drawing in the overlay in sculpt mode, and ensures all the necessary operators (pick, lasso, circle, box) handle the differences in modes correctly. The selection code so far was expecting object mode, so the `vc->obedit` object was used without further checks. Now the selection code can be called outside of edit mode, in which case the `vc->obact` object must be used instead. Similarly edit mode and sculpt mode have separate `selectmode` flags, so the correct mode property must be used from the tool settings depending on the object mode. These changes require some refactoring of unrelated selection code. Pull Request: https://projects.blender.org/blender/blender/pulls/128040 --- .../keyconfig/keymap_data/blender_default.py | 7 ++ source/blender/blenkernel/BKE_paint.hh | 4 + source/blender/blenkernel/intern/paint.cc | 14 ++- .../engines/overlay/overlay_grease_pencil.cc | 50 ++++++---- .../overlay/overlay_next_grease_pencil.hh | 15 ++- .../intern/grease_pencil_edit.cc | 12 +-- .../intern/grease_pencil_select.cc | 72 +++++++++++--- .../editors/include/ED_grease_pencil.hh | 12 ++- .../blender/editors/object/object_vgroup.cc | 3 +- .../sculpt_paint/grease_pencil_paint.cc | 2 +- .../editors/space_view3d/view3d_select.cc | 95 ++++++++++--------- 11 files changed, 193 insertions(+), 93 deletions(-) diff --git a/scripts/presets/keyconfig/keymap_data/blender_default.py b/scripts/presets/keyconfig/keymap_data/blender_default.py index 3497cd44e16..2d22cd16217 100644 --- a/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -4777,6 +4777,13 @@ def km_grease_pencil_sculpt_mode(params): "ctrl": True}, {"properties": [("mode", 'INVERT')]}), ("grease_pencil.sculpt_paint", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, {"properties": [("mode", 'SMOOTH')]}), + # Selection mode + ("wm.context_toggle", {"type": 'ONE', "value": 'PRESS'}, + {"properties": [("data_path", 'scene.tool_settings.use_gpencil_select_mask_point')]}), + ("wm.context_toggle", {"type": 'TWO', "value": 'PRESS'}, + {"properties": [("data_path", 'scene.tool_settings.use_gpencil_select_mask_stroke')]}), + ("wm.context_toggle", {"type": 'THREE', "value": 'PRESS'}, + {"properties": [("data_path", 'scene.tool_settings.use_gpencil_select_mask_segment')]}), *_template_paint_radial_control("gpencil_sculpt_paint"), op_asset_shelf_popup( "VIEW3D_AST_brush_gpencil_sculpt", diff --git a/source/blender/blenkernel/BKE_paint.hh b/source/blender/blenkernel/BKE_paint.hh index 3c71afc5b19..60633666a2a 100644 --- a/source/blender/blenkernel/BKE_paint.hh +++ b/source/blender/blenkernel/BKE_paint.hh @@ -266,6 +266,10 @@ bool BKE_paint_select_face_test(const Object *ob); * Return true when in vertex/weight paint + vertex-select mode? */ bool BKE_paint_select_vert_test(const Object *ob); +/** + * Return true when in grease pencil sculpt mode. + */ +bool BKE_paint_select_grease_pencil_test(const Object *ob); /** * used to check if selection is possible * (when we don't care if its face or vert) diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index ac684b23387..91708e18e10 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1416,9 +1416,21 @@ bool BKE_paint_select_vert_test(const Object *ob) (ob->mode & OB_MODE_WEIGHT_PAINT || ob->mode & OB_MODE_VERTEX_PAINT)); } +bool BKE_paint_select_grease_pencil_test(const Object *ob) +{ + if (ob == nullptr || ob->data == nullptr) { + return false; + } + if (ob->type == OB_GREASE_PENCIL) { + return (ob->mode & OB_MODE_SCULPT_GPENCIL_LEGACY); + } + return false; +} + bool BKE_paint_select_elem_test(const Object *ob) { - return (BKE_paint_select_vert_test(ob) || BKE_paint_select_face_test(ob)); + return (BKE_paint_select_vert_test(ob) || BKE_paint_select_face_test(ob) || + BKE_paint_select_grease_pencil_test(ob)); } bool BKE_paint_always_hide_test(const Object *ob) diff --git a/source/blender/draw/engines/overlay/overlay_grease_pencil.cc b/source/blender/draw/engines/overlay/overlay_grease_pencil.cc index 79e0920b2ac..46f9d449e86 100644 --- a/source/blender/draw/engines/overlay/overlay_grease_pencil.cc +++ b/source/blender/draw/engines/overlay/overlay_grease_pencil.cc @@ -17,26 +17,44 @@ #include "overlay_private.hh" +static void is_selection_visible(bool &r_show_points, bool &r_show_lines) +{ + using namespace blender; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const ToolSettings *ts = draw_ctx->scene->toolsettings; + const bool in_sculpt_mode = (draw_ctx->object_mode & OB_MODE_SCULPT_GPENCIL_LEGACY) != 0; + const bool in_weight_mode = (draw_ctx->object_mode & OB_MODE_WEIGHT_GPENCIL_LEGACY) != 0; + const bool flag_show_lines = (draw_ctx->v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES) != 0; + + if (in_weight_mode) { + /* Always display points in weight mode. */ + r_show_points = true; + r_show_lines = flag_show_lines; + return; + } + + if (in_sculpt_mode) { + /* Sculpt selection modes are flags and can be disabled individually. */ + static constexpr int sculpt_point_modes = GP_SCULPT_MASK_SELECTMODE_POINT | + GP_SCULPT_MASK_SELECTMODE_SEGMENT; + r_show_points = (ts->gpencil_selectmode_sculpt & sculpt_point_modes) != 0; + r_show_lines = flag_show_lines && (ts->gpencil_selectmode_sculpt != 0); + return; + } + + /* Edit selection modes are exclusive. */ + r_show_points = ELEM(ts->gpencil_selectmode_edit, GP_SELECTMODE_POINT, GP_SELECTMODE_SEGMENT); + r_show_lines = flag_show_lines; +} + void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata) { using namespace blender; OVERLAY_PassList *psl = vedata->psl; OVERLAY_PrivateData *pd = vedata->stl->pd; const DRWContextState *draw_ctx = DRW_context_state_get(); - const ToolSettings *ts = draw_ctx->scene->toolsettings; - const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(ts); - const View3D *v3d = draw_ctx->v3d; const bool use_weight = (draw_ctx->object_mode & OB_MODE_WEIGHT_GPENCIL_LEGACY) != 0; - const bool in_sculpt_mode = (draw_ctx->object_mode & OB_MODE_SCULPT_GPENCIL_LEGACY) != 0; - - const bool flag_show_lines = (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES) != 0; - const bool edit_point = selection_domain == bke::AttrDomain::Point; - const bool sculpt_point = (ts->gpencil_selectmode_sculpt & GP_SCULPT_MASK_SELECTMODE_POINT) != 0; - const bool sculpt_stroke = (ts->gpencil_selectmode_sculpt & GP_SCULPT_MASK_SELECTMODE_STROKE) != - 0; - const bool sculpt_segment = (ts->gpencil_selectmode_sculpt & - GP_SCULPT_MASK_SELECTMODE_SEGMENT) != 0; - const bool sculpt_any = sculpt_point || sculpt_stroke || sculpt_segment; GPUShader *sh; DRWShadingGroup *grp; @@ -45,9 +63,9 @@ void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata) DRW_STATE_BLEND_ALPHA; DRW_PASS_CREATE(psl->edit_grease_pencil_ps, (state | pd->clipping_state)); - const bool show_points = (edit_point && !in_sculpt_mode) || (in_sculpt_mode && sculpt_point) || - use_weight; - const bool show_lines = flag_show_lines && (sculpt_any || !in_sculpt_mode); + bool show_points = false; + bool show_lines = false; + is_selection_visible(show_points, show_lines); if (show_lines) { sh = OVERLAY_shader_edit_particle_strand(); diff --git a/source/blender/draw/engines/overlay/overlay_next_grease_pencil.hh b/source/blender/draw/engines/overlay/overlay_next_grease_pencil.hh index 61ad8a45a20..0af25498975 100644 --- a/source/blender/draw/engines/overlay/overlay_next_grease_pencil.hh +++ b/source/blender/draw/engines/overlay/overlay_next_grease_pencil.hh @@ -54,11 +54,10 @@ class GreasePencil { const View3D *v3d = state.v3d; const ToolSettings *ts = state.scene->toolsettings; - const int sculpt_select_mode = ts->gpencil_selectmode_sculpt; - const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(ts); - const bool show_edit_point = selection_domain == bke::AttrDomain::Point; - const bool show_edit_lines = (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES); + const bke::AttrDomain selection_domain_edit = ED_grease_pencil_edit_selection_domain_get(ts); + const bool show_edit_point = selection_domain_edit == bke::AttrDomain::Point; + const bool show_lines = (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES); show_points_ = show_lines_ = show_weight_ = false; @@ -72,18 +71,18 @@ class GreasePencil { case OB_MODE_EDIT: /* Edit mode. */ show_points_ = show_edit_point; - show_lines_ = show_edit_lines; + show_lines_ = show_lines; break; case OB_MODE_WEIGHT_GPENCIL_LEGACY: /* Weight paint mode. */ show_points_ = true; - show_lines_ = show_edit_lines; + show_lines_ = show_lines; show_weight_ = true; break; case OB_MODE_SCULPT_GPENCIL_LEGACY: /* Sculpt mode. */ - show_points_ = sculpt_select_mode & GP_SCULPT_MASK_SELECTMODE_POINT; - show_lines_ = show_edit_lines && (sculpt_select_mode != 0); + show_points_ = (selection_domain_edit == bke::AttrDomain::Point); + show_lines_ = show_lines && (ts->gpencil_selectmode_sculpt != 0); break; default: /* Not a Grease Pencil mode. */ diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_edit.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_edit.cc index 040ce650a9e..38f1ebe5f8c 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_edit.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_edit.cc @@ -463,7 +463,7 @@ static int grease_pencil_delete_exec(bContext *C, wmOperator * /*op*/) Object *object = CTX_data_active_object(C); GreasePencil &grease_pencil = *static_cast(object->data); - const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( + const bke::AttrDomain selection_domain = ED_grease_pencil_edit_selection_domain_get( scene->toolsettings); bool changed = false; @@ -1318,7 +1318,7 @@ static int grease_pencil_duplicate_exec(bContext *C, wmOperator * /*op*/) Object *object = CTX_data_active_object(C); GreasePencil &grease_pencil = *static_cast(object->data); - const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( + const bke::AttrDomain selection_domain = ED_grease_pencil_edit_selection_domain_get( scene->toolsettings); std::atomic changed = false; @@ -1437,7 +1437,7 @@ static int gpencil_stroke_subdivide_exec(bContext *C, wmOperator *op) const Scene *scene = CTX_data_scene(C); Object *object = CTX_data_active_object(C); GreasePencil &grease_pencil = *static_cast(object->data); - const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( + const bke::AttrDomain selection_domain = ED_grease_pencil_edit_selection_domain_get( scene->toolsettings); const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); @@ -2210,7 +2210,7 @@ static int grease_pencil_paste_strokes_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); const Scene &scene = *CTX_data_scene(C); Object *object = CTX_data_active_object(C); - const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( + const bke::AttrDomain selection_domain = ED_grease_pencil_edit_selection_domain_get( scene.toolsettings); GreasePencil &grease_pencil = *static_cast(object->data); const bool keep_world_transform = RNA_boolean_get(op->ptr, "keep_world_transform"); @@ -2289,7 +2289,7 @@ static int grease_pencil_copy_strokes_exec(bContext *C, wmOperator *op) const Scene *scene = CTX_data_scene(C); const Object *object = CTX_data_active_object(C); GreasePencil &grease_pencil = *static_cast(object->data); - const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( + const bke::AttrDomain selection_domain = ED_grease_pencil_edit_selection_domain_get( scene->toolsettings); Clipboard &clipboard = ensure_grease_pencil_clipboard(); @@ -2773,7 +2773,7 @@ static int grease_pencil_reproject_exec(bContext *C, wmOperator *op) ED_view3d_depth_override(depsgraph, region, v3d, nullptr, V3D_DEPTH_NO_GPENCIL, &view_depths); } - const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( + const bke::AttrDomain selection_domain = ED_grease_pencil_edit_selection_domain_get( scene.toolsettings); const int oldframe = int(DEG_get_ctime(depsgraph)); 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 5c973719c86..d63ba69e8c4 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc @@ -212,15 +212,16 @@ bool selection_update(const ViewContext *vc, SelectionUpdateFunc select_operation) { using namespace blender; - const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, - const_cast(vc->obedit)); - GreasePencil &grease_pencil = *static_cast(vc->obedit->data); + + Object *object = (vc->obedit ? vc->obedit : vc->obact); + const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, object); + GreasePencil &grease_pencil = *static_cast(object->data); /* Get selection domain from tool settings. */ const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( - vc->scene->toolsettings); + vc->scene->toolsettings, object); const bool use_segment_selection = ED_grease_pencil_segment_selection_enabled( - vc->scene->toolsettings); + vc->scene->toolsettings, object); bool changed = false; const Array> drawings_by_frame = @@ -252,7 +253,7 @@ bool selection_update(const ViewContext *vc, IndexMaskMemory memory; const IndexMask elements = ed::greasepencil::retrieve_editable_elements( - *vc->obedit, info, selection_domain, memory); + *object, info, selection_domain, memory); if (elements.is_empty()) { continue; } @@ -300,8 +301,8 @@ bool selection_update(const ViewContext *vc, if (changed) { /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a * generic attribute for now. */ - DEG_id_tag_update(static_cast(vc->obedit->data), ID_RECALC_GEOMETRY); - WM_event_add_notifier(vc->C, NC_GEOM | ND_DATA, vc->obedit->data); + DEG_id_tag_update(static_cast(object->data), ID_RECALC_GEOMETRY); + WM_event_add_notifier(vc->C, NC_GEOM | ND_DATA, object->data); } return changed; @@ -315,7 +316,8 @@ static int select_all_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *object = CTX_data_active_object(C); GreasePencil &grease_pencil = *static_cast(object->data); - bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(scene->toolsettings); + bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(scene->toolsettings, + object); const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { @@ -468,7 +470,8 @@ static int select_random_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *object = CTX_data_active_object(C); GreasePencil &grease_pencil = *static_cast(object->data); - bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(scene->toolsettings); + bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(scene->toolsettings, + object); const ViewContext vc = ED_view3d_viewcontext_init(C, CTX_data_depsgraph_pointer(C)); /* Note: For segment selection this doesn't work very well, because it is based on random point @@ -629,8 +632,8 @@ static int select_set_mode_exec(bContext *C, wmOperator *op) ts->gpencil_selectmode_edit = mode_new; /* Convert all drawings of the active GP to the new selection domain. */ - const bke::AttrDomain domain = ED_grease_pencil_selection_domain_get(ts); Object *object = CTX_data_active_object(C); + const bke::AttrDomain domain = ED_grease_pencil_selection_domain_get(ts, object); GreasePencil &grease_pencil = *static_cast(object->data); Span drawings = grease_pencil.drawings(); @@ -768,7 +771,8 @@ static void GREASE_PENCIL_OT_material_select(wmOperatorType *ot) } // namespace blender::ed::greasepencil -blender::bke::AttrDomain ED_grease_pencil_selection_domain_get(const ToolSettings *tool_settings) +blender::bke::AttrDomain ED_grease_pencil_edit_selection_domain_get( + const ToolSettings *tool_settings) { switch (tool_settings->gpencil_selectmode_edit) { case GP_SELECTMODE_POINT: @@ -781,11 +785,53 @@ blender::bke::AttrDomain ED_grease_pencil_selection_domain_get(const ToolSetting return blender::bke::AttrDomain::Point; } -bool ED_grease_pencil_segment_selection_enabled(const ToolSettings *tool_settings) +blender::bke::AttrDomain ED_grease_pencil_sculpt_selection_domain_get( + const ToolSettings *tool_settings) +{ + const int selectmode = tool_settings->gpencil_selectmode_sculpt; + if (selectmode & (GP_SCULPT_MASK_SELECTMODE_POINT | GP_SCULPT_MASK_SELECTMODE_SEGMENT)) { + return blender::bke::AttrDomain::Point; + } + if (selectmode & (GP_SCULPT_MASK_SELECTMODE_STROKE)) { + return blender::bke::AttrDomain::Curve; + } + return blender::bke::AttrDomain::Point; +} + +blender::bke::AttrDomain ED_grease_pencil_selection_domain_get(const ToolSettings *tool_settings, + const Object *object) +{ + if (object->mode & OB_MODE_EDIT) { + return ED_grease_pencil_edit_selection_domain_get(tool_settings); + } + if (object->mode & OB_MODE_SCULPT_GPENCIL_LEGACY) { + return ED_grease_pencil_sculpt_selection_domain_get(tool_settings); + } + return blender::bke::AttrDomain::Point; +} + +bool ED_grease_pencil_edit_segment_selection_enabled(const ToolSettings *tool_settings) { return tool_settings->gpencil_selectmode_edit == GP_SELECTMODE_SEGMENT; } +bool ED_grease_pencil_sculpt_segment_selection_enabled(const ToolSettings *tool_settings) +{ + return tool_settings->gpencil_selectmode_sculpt & GP_SCULPT_MASK_SELECTMODE_SEGMENT; +} + +bool ED_grease_pencil_segment_selection_enabled(const ToolSettings *tool_settings, + const Object *object) +{ + if (object->mode & OB_MODE_EDIT) { + return ED_grease_pencil_edit_segment_selection_enabled(tool_settings); + } + if (object->mode & OB_MODE_SCULPT_GPENCIL_LEGACY) { + return ED_grease_pencil_sculpt_segment_selection_enabled(tool_settings); + } + return false; +} + void ED_operatortypes_grease_pencil_select() { using namespace blender::ed::greasepencil; diff --git a/source/blender/editors/include/ED_grease_pencil.hh b/source/blender/editors/include/ED_grease_pencil.hh index ccc239a58e0..31422742a2b 100644 --- a/source/blender/editors/include/ED_grease_pencil.hh +++ b/source/blender/editors/include/ED_grease_pencil.hh @@ -81,11 +81,19 @@ void ED_undosys_type_grease_pencil(UndoType *undo_type); /** * Get the selection mode for Grease Pencil selection operators: point, stroke, segment. */ -blender::bke::AttrDomain ED_grease_pencil_selection_domain_get(const ToolSettings *tool_settings); +blender::bke::AttrDomain ED_grease_pencil_edit_selection_domain_get( + const ToolSettings *tool_settings); +blender::bke::AttrDomain ED_grease_pencil_sculpt_selection_domain_get( + const ToolSettings *tool_settings); +blender::bke::AttrDomain ED_grease_pencil_selection_domain_get(const ToolSettings *tool_settings, + const Object *object); /** * True if segment selection is enabled. */ -bool ED_grease_pencil_segment_selection_enabled(const ToolSettings *tool_settings); +bool ED_grease_pencil_edit_segment_selection_enabled(const ToolSettings *tool_settings); +bool ED_grease_pencil_sculpt_segment_selection_enabled(const ToolSettings *tool_settings); +bool ED_grease_pencil_segment_selection_enabled(const ToolSettings *tool_settings, + const Object *object); /** \} */ diff --git a/source/blender/editors/object/object_vgroup.cc b/source/blender/editors/object/object_vgroup.cc index bdc804b444e..7fb894d7a4a 100644 --- a/source/blender/editors/object/object_vgroup.cc +++ b/source/blender/editors/object/object_vgroup.cc @@ -1095,7 +1095,8 @@ static void vgroup_select_verts(const ToolSettings &tool_settings, Object *ob, i } } else if (ob->type == OB_GREASE_PENCIL) { - const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(&tool_settings); + const bke::AttrDomain selection_domain = ED_grease_pencil_edit_selection_domain_get( + &tool_settings); GreasePencil *grease_pencil = static_cast(ob->data); bke::greasepencil::select_from_group( *grease_pencil, selection_domain, def_group->name, bool(select)); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_paint.cc b/source/blender/editors/sculpt_paint/grease_pencil_paint.cc index d9451dfe047..1d9978427f7 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_paint.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_paint.cc @@ -1337,7 +1337,7 @@ static void deselect_stroke(const bContext &C, const IndexRange points = drawing.strokes().points_by_curve()[active_curve]; bke::CurvesGeometry &curves = drawing.strokes_for_write(); - const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( + const bke::AttrDomain selection_domain = ED_grease_pencil_edit_selection_domain_get( scene->toolsettings); bke::GSpanAttributeWriter selection = ed::curves::ensure_selection_attribute( diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index a038383de37..c8175351df9 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -463,28 +463,20 @@ static bool view3d_selectable_data(bContext *C) if (!ED_operator_region_view3d_active(C)) { return false; } - - if (ob) { - if (ob->mode & OB_MODE_EDIT) { - if (ob->type == OB_FONT) { - return false; - } - } - else { - if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)) && - !BKE_paint_select_elem_test(ob)) - { - return false; - } - if ((ob->mode & OB_MODE_WEIGHT_PAINT) && - !(BKE_paint_select_elem_test(ob) || BKE_object_pose_armature_get_with_wpaint_check(ob))) - { - return false; - } - } + if (ob == nullptr) { + return false; } - return true; + if (ob->mode & OB_MODE_EDIT) { + return ob->type != OB_FONT; + } + if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT | OB_MODE_SCULPT_GPENCIL_LEGACY)) { + return BKE_paint_select_elem_test(ob); + } + if (ob->mode & OB_MODE_WEIGHT_PAINT) { + return BKE_paint_select_elem_test(ob) && BKE_object_pose_armature_get_with_wpaint_check(ob); + } + return false; } /* helper also for box_select */ @@ -1186,11 +1178,11 @@ static bool do_lasso_select_grease_pencil(const ViewContext *vc, const eSelectOp sel_op) { using namespace blender; - const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, - const_cast(vc->obedit)); - const GreasePencil &grease_pencil = *static_cast(vc->obedit->data); + Object *object = (vc->obedit ? vc->obedit : vc->obact); + const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, const_cast(object)); + const GreasePencil &grease_pencil = *static_cast(object->data); const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( - vc->scene->toolsettings); + vc->scene->toolsettings, object); return ed::greasepencil::selection_update( vc, @@ -1203,10 +1195,10 @@ static bool do_lasso_select_grease_pencil(const ViewContext *vc, const bke::greasepencil::Layer &layer = grease_pencil.layer(info.layer_index); const bke::crazyspace::GeometryDeformation deformation = bke::crazyspace::get_evaluated_grease_pencil_drawing_deformation( - ob_eval, *vc->obedit, info.layer_index, info.frame_number); + ob_eval, *object, info.layer_index, info.frame_number); const IndexMask visible_handle_elements = ed::greasepencil::retrieve_visible_bezier_handle_elements( - *vc->obedit, info.drawing, info.layer_index, selection_domain, memory); + *object, info.drawing, info.layer_index, selection_domain, memory); const float4x4 layer_to_world = layer.to_world_space(*ob_eval); const float4x4 projection = ED_view3d_ob_project_mat_get_from_obmat(vc->rv3d, layer_to_world); @@ -1371,6 +1363,9 @@ static bool view3d_lasso_select(bContext *C, else if (BKE_paint_select_vert_test(ob)) { changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcoords, sel_op); } + else if (BKE_paint_select_grease_pencil_test(ob)) { + changed_multi |= do_lasso_select_grease_pencil(vc, mcoords, sel_op); + } else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { changed_multi |= PE_lasso_select(C, reinterpret_cast(mcoords.data()), @@ -3225,16 +3220,17 @@ static bool ed_grease_pencil_select_pick(bContext *C, Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); /* Setup view context for argument to callbacks. */ const ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph); + Object *object = (vc.obedit ? vc.obedit : vc.obact); /* Collect editable drawings. */ - const Object *ob_eval = DEG_get_evaluated_object(vc.depsgraph, const_cast(vc.obedit)); - GreasePencil &grease_pencil = *static_cast(vc.obedit->data); + const Object *ob_eval = DEG_get_evaluated_object(vc.depsgraph, const_cast(object)); + GreasePencil &grease_pencil = *static_cast(object->data); const Vector drawings = ed::greasepencil::retrieve_editable_drawings(*vc.scene, grease_pencil); /* Get selection domain from tool settings. */ const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( - vc.scene->toolsettings); + vc.scene->toolsettings, object); const ClosestGreasePencilDrawing closest = threading::parallel_reduce( drawings.index_range(), @@ -3248,17 +3244,17 @@ static bool ed_grease_pencil_select_pick(bContext *C, /* Get deformation by modifiers. */ bke::crazyspace::GeometryDeformation deformation = bke::crazyspace::get_evaluated_grease_pencil_drawing_deformation( - ob_eval, *vc.obedit, info.layer_index, info.frame_number); + ob_eval, *object, info.layer_index, info.frame_number); IndexMaskMemory memory; const IndexMask elements = ed::greasepencil::retrieve_editable_elements( - *vc.obedit, info, selection_domain, memory); + *object, info, selection_domain, memory); if (elements.is_empty()) { continue; } const IndexMask visible_handle_elements = ed::greasepencil::retrieve_visible_bezier_handle_elements( - *vc.obedit, info.drawing, info.layer_index, selection_domain, memory); + *object, info.drawing, info.layer_index, selection_domain, memory); const bke::CurvesGeometry &curves = info.drawing.strokes(); const float4x4 layer_to_world = layer.to_world_space(*ob_eval); const float4x4 projection = ED_view3d_ob_project_mat_get_from_obmat(vc.rv3d, @@ -3309,7 +3305,7 @@ static bool ed_grease_pencil_select_pick(bContext *C, ed::greasepencil::MutableDrawingInfo info = drawings[i]; IndexMaskMemory memory; const IndexMask elements = ed::greasepencil::retrieve_editable_elements( - *vc.obedit, info, selection_domain, memory); + *object, info, selection_domain, memory); if (elements.is_empty()) { continue; } @@ -3470,6 +3466,9 @@ static int view3d_select_exec(bContext *C, wmOperator *op) else if (BKE_paint_select_vert_test(obact)) { changed = ed_wpaint_vertex_select_pick(C, mval, ¶ms, obact); } + else if (BKE_paint_select_grease_pencil_test(obact)) { + changed = ed_grease_pencil_select_pick(C, mval, params); + } else { changed = ed_object_select_pick(C, mval, ¶ms, center, enumerate, object_only); } @@ -4282,11 +4281,11 @@ static bool do_grease_pencil_box_select(const ViewContext *vc, const eSelectOp sel_op) { using namespace blender; - const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, - const_cast(vc->obedit)); - const GreasePencil &grease_pencil = *static_cast(vc->obedit->data); + Object *object = (vc->obedit ? vc->obedit : vc->obact); + const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, const_cast(object)); + const GreasePencil &grease_pencil = *static_cast(object->data); const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( - vc->scene->toolsettings); + vc->scene->toolsettings, object); return ed::greasepencil::selection_update( vc, @@ -4299,10 +4298,10 @@ static bool do_grease_pencil_box_select(const ViewContext *vc, const bke::greasepencil::Layer &layer = grease_pencil.layer(info.layer_index); const bke::crazyspace::GeometryDeformation deformation = bke::crazyspace::get_evaluated_grease_pencil_drawing_deformation( - ob_eval, *vc->obedit, info.layer_index, info.frame_number); + ob_eval, *object, info.layer_index, info.frame_number); const IndexMask visible_handle_elements = ed::greasepencil::retrieve_visible_bezier_handle_elements( - *vc->obedit, info.drawing, info.layer_index, selection_domain, memory); + *object, info.drawing, info.layer_index, selection_domain, memory); const float4x4 layer_to_world = layer.to_world_space(*ob_eval); const float4x4 projection = ED_view3d_ob_project_mat_get_from_obmat(vc->rv3d, layer_to_world); @@ -4429,6 +4428,9 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) { changed_multi = do_paintvert_box_select(&vc, wm_userdata, &rect, sel_op); } + else if (vc.obact && BKE_paint_select_grease_pencil_test(vc.obact)) { + changed_multi = do_grease_pencil_box_select(&vc, &rect, sel_op); + } else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) { changed_multi = PE_box_select(C, &rect, sel_op); } @@ -5146,11 +5148,11 @@ static bool grease_pencil_circle_select(const ViewContext *vc, const float rad) { using namespace blender; - const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, - const_cast(vc->obedit)); - const GreasePencil &grease_pencil = *static_cast(vc->obedit->data); + Object *object = (vc->obedit ? vc->obedit : vc->obact); + const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, const_cast(object)); + const GreasePencil &grease_pencil = *static_cast(object->data); const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( - vc->scene->toolsettings); + vc->scene->toolsettings, object); return ed::greasepencil::selection_update( vc, @@ -5163,10 +5165,10 @@ static bool grease_pencil_circle_select(const ViewContext *vc, const bke::greasepencil::Layer &layer = grease_pencil.layer(info.layer_index); const bke::crazyspace::GeometryDeformation deformation = bke::crazyspace::get_evaluated_grease_pencil_drawing_deformation( - ob_eval, *vc->obedit, info.layer_index, info.frame_number); + ob_eval, *object, info.layer_index, info.frame_number); const IndexMask visible_handle_elements = ed::greasepencil::retrieve_visible_bezier_handle_elements( - *vc->obedit, info.drawing, info.layer_index, selection_domain, memory); + *object, info.drawing, info.layer_index, selection_domain, memory); const float4x4 layer_to_world = layer.to_world_space(*ob_eval); const float4x4 projection = ED_view3d_ob_project_mat_get_from_obmat(vc->rv3d, layer_to_world); @@ -5392,6 +5394,9 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) else if (BKE_paint_select_vert_test(obact)) { paint_vertsel_circle_select(&vc, wm_userdata, sel_op, mval, float(radius)); } + else if (BKE_paint_select_grease_pencil_test(obact)) { + grease_pencil_circle_select(&vc, sel_op, mval, float(radius)); + } else if (obact->mode & OB_MODE_POSE) { pose_circle_select(&vc, sel_op, mval, float(radius)); ED_outliner_select_sync_from_pose_bone_tag(C);