diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index 5353686d53c..b2d2bf433bf 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -7950,6 +7950,8 @@ class VIEW3D_PT_overlay_grease_pencil_options(Panel): col.prop(overlay, "use_gpencil_edit_lines", text="Edit Lines") col = split.column() col.prop(overlay, "use_gpencil_multiedit_line_only", text="Only in Multiframe") + row = layout.row() + row.prop(overlay, "display_handle", text="Handles") if ob.mode == 'EDIT': split = layout.split() diff --git a/source/blender/draw/engines/overlay/overlay_grease_pencil.hh b/source/blender/draw/engines/overlay/overlay_grease_pencil.hh index 04a59beafae..060de5f609f 100644 --- a/source/blender/draw/engines/overlay/overlay_grease_pencil.hh +++ b/source/blender/draw/engines/overlay/overlay_grease_pencil.hh @@ -35,6 +35,7 @@ namespace blender::draw::overlay { class GreasePencil : Overlay { private: PassSimple edit_grease_pencil_ps_ = {"GPencil Edit"}; + PassSimple::Sub *edit_handles_ = nullptr; PassSimple::Sub *edit_points_ = nullptr; PassSimple::Sub *edit_lines_ = nullptr; @@ -107,6 +108,7 @@ class GreasePencil : Overlay { break; } + edit_handles_ = nullptr; edit_points_ = nullptr; edit_lines_ = nullptr; @@ -119,6 +121,15 @@ class GreasePencil : Overlay { DRW_STATE_BLEND_ALPHA, state.clipping_plane_count); + { + auto &sub = pass.sub("Handles"); + sub.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count); + sub.shader_set(res.shaders->curve_edit_handles.get()); + sub.push_constant("show_curve_handles", state.overlay.handle_display != CURVE_HANDLE_NONE); + sub.push_constant("curve_handle_display", int(state.overlay.handle_display)); + edit_handles_ = ⊂ + } + if (show_points_) { auto &sub = pass.sub("Points"); sub.shader_set(res.shaders->curve_edit_points.get()); @@ -126,6 +137,7 @@ class GreasePencil : Overlay { sub.push_constant("use_weight", show_weight_); sub.push_constant("use_grease_pencil", true); sub.push_constant("do_stroke_endpoints", show_direction); + sub.push_constant("curve_handle_display", int(state.overlay.handle_display)); edit_points_ = ⊂ } @@ -173,6 +185,12 @@ class GreasePencil : Overlay { Object *ob = ob_ref.object; + { + gpu::Batch *geom = DRW_cache_grease_pencil_edit_handles_get(state.scene, ob); + if (geom) { + edit_handles_->draw_expand(geom, GPU_PRIM_TRIS, 8, 1, manager.unique_handle(ob_ref)); + } + } if (show_points_) { gpu::Batch *geom = show_weight_ ? DRW_cache_grease_pencil_weight_points_get(state.scene, ob) : diff --git a/source/blender/draw/intern/draw_cache.hh b/source/blender/draw/intern/draw_cache.hh index 7a3133883c6..5688efc0115 100644 --- a/source/blender/draw/intern/draw_cache.hh +++ b/source/blender/draw/intern/draw_cache.hh @@ -152,6 +152,7 @@ gpu::Batch *DRW_cache_volume_selection_surface_get(Object *ob); gpu::Batch *DRW_cache_grease_pencil_get(const Scene *scene, Object *ob); gpu::Batch *DRW_cache_grease_pencil_edit_points_get(const Scene *scene, Object *ob); gpu::Batch *DRW_cache_grease_pencil_edit_lines_get(const Scene *scene, Object *ob); +gpu::Batch *DRW_cache_grease_pencil_edit_handles_get(const Scene *scene, Object *ob); gpu::VertBuf *DRW_cache_grease_pencil_position_buffer_get(const Scene *scene, Object *ob); gpu::VertBuf *DRW_cache_grease_pencil_color_buffer_get(const Scene *scene, Object *ob); gpu::Batch *DRW_cache_grease_pencil_weight_points_get(const Scene *scene, Object *ob); diff --git a/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc b/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc index cafd4d4cc67..f5245586c82 100644 --- a/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc @@ -36,6 +36,14 @@ namespace blender::draw { +#define EDIT_CURVES_NURBS_CONTROL_POINT (1u) +#define EDIT_CURVES_BEZIER_HANDLE (1u << 1) +#define EDIT_CURVES_ACTIVE_HANDLE (1u << 2) +/* Bezier curve control point lying on the curve. + * The one between left and right handles. */ +#define EDIT_CURVES_BEZIER_KNOT (1u << 3) +#define EDIT_CURVES_HANDLE_TYPES_SHIFT (4u) + struct GreasePencilBatchCache { /** Instancing Data */ gpu::VertBuf *vbo; @@ -47,6 +55,7 @@ struct GreasePencilBatchCache { gpu::Batch *lines_batch; gpu::Batch *edit_points; gpu::Batch *edit_lines; + gpu::Batch *edit_handles; /* Crazy-space point positions for original points. */ gpu::VertBuf *edit_points_pos; @@ -64,6 +73,21 @@ struct GreasePencilBatchCache { /* Indices for lines segments. */ gpu::IndexBuf *edit_line_indices; + /* Additional data needed for shader to choose color for each point in edit_points_pos. + * If first bit is set, then point is NURBS control point. EDIT_CURVES_NURBS_CONTROL_POINT is + * used to set and test. If second, then point is Bezier handle point. Set and tested with + * EDIT_CURVES_BEZIER_HANDLE. + * In Bezier case two handle types of HandleType are also encoded. + * Byte structure for Bezier knot point (handle middle point): + * | left handle type | right handle type | | BEZIER| NURBS| + * | 7 6 | 5 4 | 3 2 | 1 | 0 | + * + * If it is left or right handle point, then same handle type is repeated in both slots. + */ + gpu::VertBuf *edit_points_info; + + gpu::IndexBuf *edit_handles_ibo; + /** Cache is dirty. */ bool is_dirty; /** Last cached frame. */ @@ -164,11 +188,14 @@ static void grease_pencil_batch_cache_clear(GreasePencil &grease_pencil) GPU_BATCH_DISCARD_SAFE(cache->lines_batch); GPU_BATCH_DISCARD_SAFE(cache->edit_points); GPU_BATCH_DISCARD_SAFE(cache->edit_lines); + GPU_BATCH_DISCARD_SAFE(cache->edit_handles); GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_pos); GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_selection); GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_vflag); GPU_INDEXBUF_DISCARD_SAFE(cache->edit_points_indices); + GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_info); + GPU_INDEXBUF_DISCARD_SAFE(cache->edit_handles_ibo); GPU_VERTBUF_DISCARD_SAFE(cache->edit_line_pos); GPU_VERTBUF_DISCARD_SAFE(cache->edit_line_selection); @@ -598,16 +625,12 @@ static void index_buf_add_nurbs_lines(Object &object, *r_drawing_line_index = line_index; } -static void index_buf_add_bezier_lines(Object &object, - const bke::greasepencil::Drawing &drawing, - int layer_index, - IndexMaskMemory &memory, - MutableSpan lines_data, - int *r_drawing_line_index, - int *r_drawing_line_start_offset) +static void index_buf_add_bezier_handle_lines(const IndexMask bezier_points, + const int all_points, + MutableSpan handle_lines, + int *r_drawing_line_index, + int *r_drawing_line_start_offset) { - const IndexMask bezier_points = ed::greasepencil::retrieve_visible_bezier_handle_points( - object, drawing, layer_index, memory); if (bezier_points.is_empty()) { return; } @@ -615,17 +638,15 @@ static void index_buf_add_bezier_lines(Object &object, const int offset = *r_drawing_line_start_offset; int line_index = *r_drawing_line_index; - /* Add all bezier points. */ - for (const int point : bezier_points.index_range()) { - lines_data[line_index++] = point + bezier_points.size() * 0 + offset; - lines_data[line_index++] = point + bezier_points.size() * 1 + offset; - lines_data[line_index++] = point + bezier_points.size() * 2 + offset; - - lines_data[line_index++] = gpu::RESTART_INDEX; - } + /* Add all bezier handle lines. */ + bezier_points.foreach_index([&](const int point_i, const int pos) { + handle_lines[line_index++] = uint2(offset + all_points + pos + bezier_points.size() * 0, + offset + point_i); + handle_lines[line_index++] = uint2(offset + all_points + pos + bezier_points.size() * 1, + offset + point_i); + }); *r_drawing_line_index = line_index; - *r_drawing_line_start_offset += bezier_points.size() * 3; } static void index_buf_add_points(Object &object, @@ -658,16 +679,17 @@ static void index_buf_add_points(Object &object, *r_drawing_start_offset += curves.points_num(); } -static void index_buf_add_bezier_line_points(Object &object, - const bke::greasepencil::Drawing &drawing, - int layer_index, - IndexMaskMemory &memory, +static uint32_t bezier_data_value(int8_t handle_type, bool is_active) +{ + return (handle_type << EDIT_CURVES_HANDLE_TYPES_SHIFT) | EDIT_CURVES_BEZIER_HANDLE | + (is_active ? EDIT_CURVES_ACTIVE_HANDLE : 0); +} + +static void index_buf_add_bezier_line_points(const IndexMask bezier_points, MutableSpan points_data, int *r_drawing_point_index, int *r_drawing_start_offset) { - const IndexMask bezier_points = ed::greasepencil::retrieve_visible_bezier_handle_points( - object, drawing, layer_index, memory); if (bezier_points.is_empty()) { return; } @@ -729,6 +751,9 @@ static void grease_pencil_edit_batch_ensure(Object &object, static const GPUVertFormat format_edit_line_selection = GPU_vertformat_from_attribute( "selection", gpu::VertAttrType::SFLOAT_32); + static const GPUVertFormat format_edit_points_info = GPU_vertformat_from_attribute( + "data", gpu::VertAttrType::UINT_32); + GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY; cache->edit_points_pos = GPU_vertbuf_create_with_format_ex(format_edit_points_pos, vbo_flag); cache->edit_points_selection = GPU_vertbuf_create_with_format_ex(format_edit_points_selection, @@ -737,6 +762,7 @@ static void grease_pencil_edit_batch_ensure(Object &object, cache->edit_line_pos = GPU_vertbuf_create_with_format_ex(format_edit_line_pos, vbo_flag); cache->edit_line_selection = GPU_vertbuf_create_with_format_ex(format_edit_line_selection, vbo_flag); + cache->edit_points_info = GPU_vertbuf_create_with_format_ex(format_edit_points_info, vbo_flag); int total_points_num = 0; for (const ed::greasepencil::DrawingInfo &info : drawings) { @@ -760,7 +786,7 @@ static void grease_pencil_edit_batch_ensure(Object &object, for (const ed::greasepencil::DrawingInfo &info : drawings) { IndexMaskMemory memory; const IndexMask bezier_points = ed::greasepencil::retrieve_visible_bezier_handle_points( - object, info.drawing, info.layer_index, memory); + object, info.drawing, info.layer_index, CURVE_HANDLE_ALL, memory); total_bezier_point_num += bezier_points.size(); } @@ -776,8 +802,6 @@ static void grease_pencil_edit_batch_ensure(Object &object, /* Add two for each bezier point, (one left, one right). */ total_points_num += total_bezier_point_num * 2; - /* Add three for each bezier point, (one left, one right and one for the center point). */ - total_line_points_num += total_bezier_point_num * 3; if (total_points_num == 0) { return; @@ -788,18 +812,22 @@ static void grease_pencil_edit_batch_ensure(Object &object, GPU_vertbuf_data_alloc(*cache->edit_points_vflag, total_points_num); GPU_vertbuf_data_alloc(*cache->edit_line_pos, total_line_points_num); GPU_vertbuf_data_alloc(*cache->edit_line_selection, total_line_points_num); + GPU_vertbuf_data_alloc(*cache->edit_points_info, total_points_num); MutableSpan edit_points = cache->edit_points_pos->data(); MutableSpan edit_points_selection = cache->edit_points_selection->data(); MutableSpan edit_points_vflag = cache->edit_points_vflag->data(); MutableSpan edit_line_points = cache->edit_line_pos->data(); MutableSpan edit_line_selection = cache->edit_line_selection->data(); + MutableSpan edit_points_info = cache->edit_points_info->data(); edit_points_selection.fill(0.0f); edit_points_vflag.fill(0); + edit_points_info.fill(0); edit_line_selection.fill(0.0f); int visible_points_num = 0; int total_line_ids_num = 0; + int total_bezier_num = 0; int drawing_start_offset = 0; int drawing_line_start_offset = 0; for (const ed::greasepencil::DrawingInfo &info : drawings) { @@ -838,9 +866,9 @@ static void grease_pencil_edit_batch_ensure(Object &object, /* Flag the start and end points. */ for (const int curve_i : curves.curves_range()) { - const IndexRange points = points_by_curve[curve_i].shift(drawing_start_offset); - edit_points_vflag[points.first()] |= GREASE_PENCIL_EDIT_STROKE_START; - edit_points_vflag[points.last()] |= GREASE_PENCIL_EDIT_STROKE_END; + const IndexRange sub_points = points_by_curve[curve_i].shift(drawing_start_offset); + edit_points_vflag[sub_points.first()] |= GREASE_PENCIL_EDIT_STROKE_START; + edit_points_vflag[sub_points.last()] |= GREASE_PENCIL_EDIT_STROKE_END; } const IndexMask selected_editable_points = @@ -901,7 +929,7 @@ static void grease_pencil_edit_batch_ensure(Object &object, &total_line_ids_num); const IndexMask bezier_points = ed::greasepencil::retrieve_visible_bezier_handle_points( - object, info.drawing, info.layer_index, memory); + object, info.drawing, info.layer_index, CURVE_HANDLE_ALL, memory); if (bezier_points.is_empty()) { continue; } @@ -938,48 +966,23 @@ static void grease_pencil_edit_batch_ensure(Object &object, array_utils::gather(selected_left, bezier_points, selection_slice_left); array_utils::gather(selected_right, bezier_points, selection_slice_right); - const IndexRange eval_left_slice = IndexRange(drawing_line_start_offset, bezier_points.size()); - const IndexRange eval_center_slice = IndexRange( - drawing_line_start_offset + bezier_points.size(), bezier_points.size()); - const IndexRange eval_right_slice = IndexRange( - drawing_line_start_offset + bezier_points.size() * 2, bezier_points.size()); + const VArray types_left = curves.handle_types_left(); + const VArray types_right = curves.handle_types_right(); - MutableSpan positions_eval_left_slice = edit_line_points.slice(eval_left_slice); - MutableSpan positions_eval_center_slice = edit_line_points.slice(eval_center_slice); - MutableSpan positions_eval_right_slice = edit_line_points.slice(eval_right_slice); + bezier_points.foreach_index([&](const int point_i, const int pos) { + const bool selected = selected_point[point_i] || selected_left[point_i] || + selected_right[point_i]; + edit_points_info.slice(left_slice)[pos] = bezier_data_value(types_left[point_i], selected); + edit_points_info.slice(right_slice)[pos] = bezier_data_value(types_right[point_i], selected); - array_utils::copy(positions_slice_left.as_span(), positions_eval_left_slice); - array_utils::copy(positions_slice_right.as_span(), positions_eval_right_slice); - - /* This will copy over the position but without the layer transform. */ - array_utils::gather(positions, bezier_points, positions_eval_center_slice); - - /* Go through the position and apply the layer transform. */ - threading::parallel_for(bezier_points.index_range(), 1024, [&](const IndexRange range) { - copy_transformed_positions(positions_eval_center_slice, - range, - layer_space_to_object_space, - positions_eval_center_slice); + edit_points_info.slice(points)[point_i] = EDIT_CURVES_BEZIER_KNOT; }); - MutableSpan selection_eval_slice_left = edit_line_selection.slice(eval_left_slice); - MutableSpan selection_eval_slice_center = edit_line_selection.slice(eval_center_slice); - MutableSpan selection_eval_slice_right = edit_line_selection.slice(eval_right_slice); - array_utils::copy(selection_slice_left.as_span(), selection_eval_slice_left); - array_utils::copy(selection_slice_right.as_span(), selection_eval_slice_right); - - array_utils::gather(selected_point, bezier_points, selection_eval_slice_center); - /* Add two for each bezier point, (one left, one right). */ visible_points_num += bezier_points.size() * 2; drawing_start_offset += bezier_points.size() * 2; - /* Add three for each bezier point, (one left, one right and one for the center point). */ - drawing_line_start_offset += bezier_points.size() * 3; - total_line_ids_num += bezier_points.size() * 3; - - /* Add one id for the restart after every bezier. */ - total_line_ids_num += bezier_points.size(); + total_bezier_num += bezier_points.size(); } GPUIndexBufBuilder lines_builder; @@ -993,6 +996,11 @@ static void grease_pencil_edit_batch_ensure(Object &object, MutableSpan points_data = GPU_indexbuf_get_data(&points_builder); int points_ibo_index = 0; + GPUIndexBufBuilder handles_builder; + GPU_indexbuf_init(&handles_builder, GPU_PRIM_LINES, total_bezier_num * 2, total_points_num); + MutableSpan handle_lines = GPU_indexbuf_get_data(&handles_builder).cast(); + + int handle_lines_id = 0; /* Fill line index and point index buffers with data. */ drawing_start_offset = 0; drawing_line_start_offset = 0; @@ -1009,6 +1017,9 @@ static void grease_pencil_edit_batch_ensure(Object &object, &drawing_line_start_offset); if (!layer->is_locked()) { + const IndexMask bezier_points = ed::greasepencil::retrieve_visible_bezier_handle_points( + object, info.drawing, info.layer_index, CURVE_HANDLE_ALL, memory); + index_buf_add_nurbs_lines(object, info.drawing, info.layer_index, @@ -1016,13 +1027,11 @@ static void grease_pencil_edit_batch_ensure(Object &object, lines_data, &lines_ibo_index, &drawing_line_start_offset); - index_buf_add_bezier_lines(object, - info.drawing, - info.layer_index, - memory, - lines_data, - &lines_ibo_index, - &drawing_line_start_offset); + index_buf_add_bezier_handle_lines(bezier_points, + info.drawing.strokes().points_num(), + handle_lines, + &handle_lines_id, + &drawing_start_offset); index_buf_add_points(object, info.drawing, info.layer_index, @@ -1030,35 +1039,38 @@ static void grease_pencil_edit_batch_ensure(Object &object, points_data, &points_ibo_index, &drawing_start_offset); - index_buf_add_bezier_line_points(object, - info.drawing, - info.layer_index, - memory, - points_data, - &points_ibo_index, - &drawing_start_offset); + index_buf_add_bezier_line_points( + bezier_points, points_data, &points_ibo_index, &drawing_start_offset); } } cache->edit_line_indices = GPU_indexbuf_build_ex(&lines_builder, 0, total_points_num, true); cache->edit_points_indices = GPU_indexbuf_build_ex(&points_builder, 0, total_points_num, false); + cache->edit_handles_ibo = GPU_indexbuf_build_ex(&handles_builder, 0, total_points_num, false); /* Create the batches */ cache->edit_points = GPU_batch_create( GPU_PRIM_POINTS, cache->edit_points_pos, cache->edit_points_indices); GPU_batch_vertbuf_add(cache->edit_points, cache->edit_points_selection, false); GPU_batch_vertbuf_add(cache->edit_points, cache->edit_points_vflag, false); + GPU_batch_vertbuf_add(cache->edit_points, cache->edit_points_info, false); cache->edit_lines = GPU_batch_create( GPU_PRIM_LINE_STRIP, cache->edit_line_pos, cache->edit_line_indices); GPU_batch_vertbuf_add(cache->edit_lines, cache->edit_line_selection, false); + cache->edit_handles = GPU_batch_create( + GPU_PRIM_LINES, cache->edit_points_pos, cache->edit_handles_ibo); + GPU_batch_vertbuf_add(cache->edit_handles, cache->edit_points_info, false); + GPU_batch_vertbuf_add(cache->edit_handles, cache->edit_points_selection, false); + /* Allow creation of buffer texture. */ GPU_vertbuf_use(cache->edit_points_pos); GPU_vertbuf_use(cache->edit_line_pos); GPU_vertbuf_use(cache->edit_points_selection); GPU_vertbuf_use(cache->edit_line_selection); GPU_vertbuf_use(cache->edit_points_vflag); + GPU_vertbuf_use(cache->edit_points_info); cache->is_dirty = false; } @@ -1496,7 +1508,7 @@ gpu::Batch *DRW_cache_grease_pencil_edit_points_get(const Scene *scene, Object * GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil); grease_pencil_edit_batch_ensure(*ob, grease_pencil, *scene); - /* Can be `nullptr` when there's no grease pencil drawing visible. */ + /* Can be `nullptr` when there's no Grease Pencil drawing visible. */ return cache->edit_points; } @@ -1506,10 +1518,20 @@ gpu::Batch *DRW_cache_grease_pencil_edit_lines_get(const Scene *scene, Object *o GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil); grease_pencil_edit_batch_ensure(*ob, grease_pencil, *scene); - /* Can be `nullptr` when there's no grease pencil drawing visible. */ + /* Can be `nullptr` when there's no Grease Pencil drawing visible. */ return cache->edit_lines; } +gpu::Batch *DRW_cache_grease_pencil_edit_handles_get(const Scene *scene, Object *ob) +{ + GreasePencil &grease_pencil = DRW_object_get_data_for_drawing(*ob); + GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil); + grease_pencil_edit_batch_ensure(*ob, grease_pencil, *scene); + + /* Can be `nullptr` when there's no Grease Pencil drawing visible. */ + return cache->edit_handles; +} + gpu::VertBuf *DRW_cache_grease_pencil_position_buffer_get(const Scene *scene, Object *ob) { GreasePencil &grease_pencil = DRW_object_get_data_for_drawing(*ob); @@ -1534,7 +1556,7 @@ gpu::Batch *DRW_cache_grease_pencil_weight_points_get(const Scene *scene, Object GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil); grease_pencil_weight_batch_ensure(*ob, grease_pencil, *scene); - /* Can be `nullptr` when there's no grease pencil drawing visible. */ + /* Can be `nullptr` when there's no Grease Pencil drawing visible. */ return cache->edit_points; } @@ -1544,7 +1566,7 @@ gpu::Batch *DRW_cache_grease_pencil_weight_lines_get(const Scene *scene, Object GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil); grease_pencil_weight_batch_ensure(*ob, grease_pencil, *scene); - /* Can be `nullptr` when there's no grease pencil drawing visible. */ + /* Can be `nullptr` when there's no Grease Pencil drawing visible. */ return cache->edit_lines; } diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc index 76a2d090352..a83179eb383 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc @@ -11,6 +11,7 @@ #include "BKE_brush.hh" #include "BKE_colortools.hh" #include "BKE_context.hh" +#include "BKE_curves_utils.hh" #include "BKE_grease_pencil.hh" #include "BKE_lib_id.hh" #include "BKE_material.hh" @@ -1186,10 +1187,9 @@ IndexMask retrieve_visible_points(Object &object, }); } -IndexMask retrieve_visible_bezier_handle_points(Object &object, - const bke::greasepencil::Drawing &drawing, - const int layer_index, - IndexMaskMemory &memory) +IndexMask retrieve_visible_bezier_strokes(Object &object, + const bke::greasepencil::Drawing &drawing, + IndexMaskMemory &memory) { const bke::CurvesGeometry &curves = drawing.strokes(); @@ -1197,8 +1197,79 @@ IndexMask retrieve_visible_bezier_handle_points(Object &object, return IndexMask(0); } - /* Make sure that the handle position attributes exists. */ - if (curves.handle_positions_left().is_empty() || curves.handle_positions_right().is_empty()) { + const IndexRange curves_range = curves.curves_range(); + const VArray curve_types = curves.curve_types(); + const std::array type_counts = curves.curve_type_counts(); + + const IndexMask bezier_strokes = bke::curves::indices_for_type( + curve_types, type_counts, CURVE_TYPE_BEZIER, curves_range, memory); + + const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes( + object, drawing, memory); + + return IndexMask::from_intersection(visible_strokes, bezier_strokes, memory); +} + +IndexMask retrieve_visible_bezier_points(Object &object, + const bke::greasepencil::Drawing &drawing, + IndexMaskMemory &memory) +{ + const bke::CurvesGeometry &curves = drawing.strokes(); + + if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) { + return IndexMask(0); + } + + const IndexMask visible_bezier_strokes = retrieve_visible_bezier_strokes( + object, drawing, memory); + + return IndexMask::from_ranges(curves.points_by_curve(), visible_bezier_strokes, memory); +} + +IndexMask retrieve_visible_bezier_handle_strokes(Object &object, + const bke::greasepencil::Drawing &drawing, + const int handle_display, + IndexMaskMemory &memory) +{ + if (handle_display == CURVE_HANDLE_NONE) { + return IndexMask(0); + } + + const bke::CurvesGeometry &curves = drawing.strokes(); + + if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) { + return IndexMask(0); + } + + const IndexMask visible_bezier_strokes = retrieve_visible_bezier_strokes( + object, drawing, memory); + + if (handle_display == CURVE_HANDLE_ALL) { + return visible_bezier_strokes; + } + + /* handle_display == CURVE_HANDLE_SELECTED */ + const IndexMask selected_strokes = ed::curves::retrieve_selected_curves(curves, memory); + return IndexMask::from_intersection(visible_bezier_strokes, selected_strokes, memory); +} + +IndexMask retrieve_visible_bezier_handle_points(Object &object, + const bke::greasepencil::Drawing &drawing, + const int layer_index, + const int handle_display, + IndexMaskMemory &memory) +{ + if (handle_display == CURVE_HANDLE_NONE) { + return IndexMask(0); + } + else if (handle_display == CURVE_HANDLE_ALL) { + return retrieve_visible_bezier_points(object, drawing, memory); + } + /* else handle_display == CURVE_HANDLE_SELECTED */ + + const bke::CurvesGeometry &curves = drawing.strokes(); + + if (!curves.has_curve_with_type(CURVE_TYPE_BEZIER)) { return IndexMask(0); } @@ -1230,15 +1301,16 @@ IndexMask retrieve_visible_bezier_handle_elements(Object &object, const bke::greasepencil::Drawing &drawing, const int layer_index, const bke::AttrDomain selection_domain, + const int handle_display, IndexMaskMemory &memory) { if (selection_domain == bke::AttrDomain::Curve) { - return ed::greasepencil::retrieve_editable_and_selected_strokes( - object, drawing, layer_index, memory); + return ed::greasepencil::retrieve_visible_bezier_handle_strokes( + object, drawing, handle_display, memory); } if (selection_domain == bke::AttrDomain::Point) { return ed::greasepencil::retrieve_visible_bezier_handle_points( - object, drawing, layer_index, memory); + object, drawing, layer_index, handle_display, memory); } return {}; } diff --git a/source/blender/editors/include/ED_grease_pencil.hh b/source/blender/editors/include/ED_grease_pencil.hh index 3061eac3122..5d1f786da4e 100644 --- a/source/blender/editors/include/ED_grease_pencil.hh +++ b/source/blender/editors/include/ED_grease_pencil.hh @@ -411,14 +411,27 @@ IndexMask retrieve_visible_points(Object &object, const bke::greasepencil::Drawing &drawing, IndexMaskMemory &memory); +IndexMask retrieve_visible_bezier_strokes(Object &object, + const bke::greasepencil::Drawing &drawing, + IndexMaskMemory &memory); +IndexMask retrieve_visible_bezier_points(Object &object, + const bke::greasepencil::Drawing &drawing, + IndexMaskMemory &memory); + +IndexMask retrieve_visible_bezier_handle_strokes(Object &object, + const bke::greasepencil::Drawing &drawing, + int handle_display, + IndexMaskMemory &memory); IndexMask retrieve_visible_bezier_handle_points(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, + int handle_display, IndexMaskMemory &memory); IndexMask retrieve_visible_bezier_handle_elements(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, bke::AttrDomain selection_domain, + int handle_display, IndexMaskMemory &memory); IndexMask retrieve_editable_and_selected_strokes(Object &grease_pencil_object, diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index 5bbbd3f9401..afd1f309f24 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -1187,7 +1187,12 @@ static bool do_lasso_select_grease_pencil(const ViewContext *vc, ob_eval, *object, info.drawing); const IndexMask visible_handle_elements = ed::greasepencil::retrieve_visible_bezier_handle_elements( - *object, info.drawing, info.layer_index, selection_domain, memory); + *object, + info.drawing, + info.layer_index, + selection_domain, + vc->v3d->overlay.handle_display, + 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); @@ -3365,7 +3370,12 @@ static bool ed_grease_pencil_select_pick(bContext *C, } const IndexMask visible_handle_elements = ed::greasepencil::retrieve_visible_bezier_handle_elements( - *object, info.drawing, info.layer_index, selection_domain, memory); + *object, + info.drawing, + info.layer_index, + selection_domain, + vc.v3d->overlay.handle_display, + 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, @@ -4416,7 +4426,12 @@ static bool do_grease_pencil_box_select(const ViewContext *vc, ob_eval, *object, info.drawing); const IndexMask visible_handle_elements = ed::greasepencil::retrieve_visible_bezier_handle_elements( - *object, info.drawing, info.layer_index, selection_domain, memory); + *object, + info.drawing, + info.layer_index, + selection_domain, + vc->v3d->overlay.handle_display, + 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); @@ -5299,7 +5314,12 @@ static bool grease_pencil_circle_select(const ViewContext *vc, ob_eval, *object, info.drawing); const IndexMask visible_handle_elements = ed::greasepencil::retrieve_visible_bezier_handle_elements( - *object, info.drawing, info.layer_index, selection_domain, memory); + *object, + info.drawing, + info.layer_index, + selection_domain, + vc->v3d->overlay.handle_display, + 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);