46 return std::clamp(index,
int(
range.first()),
int(
range.last()));
58 const int curve_index,
67 const IndexRange segments = segments_by_curve[curve_index];
69 for (
const int segment_i : segments) {
73 if (segment_i < segments.
last()) {
74 const int next_segment_i = segment_i + 1;
79 const int first_point_i = (segment_fraction == 0.0f ?
82 const int next_first_point_i = (next_segment_fraction == 0.0f ?
83 next_segment_point_i :
93 const int first_point_i = (segment_fraction == 0.0f ?
97 const int next_first_point_i = (first_segment_fraction == 0.0f ?
98 first_segment_point_i :
105 fn(segment_i, points_range1, points_range2);
108 return segments.
size();
124 curves, selection_domain, create_type, attribute_name);
144 if (attribute_name !=
".selection") {
149 if (point_selection_mask.
is_empty()) {
155 curves, point_selection_mask,
GrainSize(512), memory);
162 curves, changed_curve_mask, screen_space_positions, tree_data, tree_data_range);
171 point_selection_mask.
to_bools(changed_points);
174 for (
const int point_i :
range) {
175 if (changed_points[point_i]) {
182 for (
const int point_i :
range) {
189 for (const int curve_i : range) {
190 const IndexRange points = points_by_curve[curve_i];
192 const int num_segments = foreach_curve_segment(
196 [&](const int , const IndexRange points1, const IndexRange points2) {
197 if (test_points_range(points1) || test_points_range(points2)) {
198 update_points_range(points1);
199 update_points_range(points2);
202 if (num_segments == 0 && test_points_range(points)) {
204 update_points_range(points);
209 attribute_writer.finish();
229 bool changed =
false;
231 ed::greasepencil::retrieve_editable_drawings_grouped_per_frame(*vc->
scene, grease_pencil);
234 if (drawings.is_empty()) {
237 const int frame_number = drawings.first().frame_number;
241 BLI_SCOPED_DEFER([&]() { ed::greasepencil::free_curves_2d_bvh_data(tree_data); });
242 if (use_segment_selection) {
243 tree_data = ed::greasepencil::build_curves_2d_bvh_from_visible(
244 *vc, *ob_eval, grease_pencil, drawings, frame_number);
248 for (
const int i_drawing : drawings.index_range()) {
255 ed::curves::get_curves_selection_attribute_names(curves);
258 const IndexMask elements = ed::greasepencil::retrieve_editable_elements(
259 *
object,
info, selection_domain, memory);
264 for (
const StringRef attribute_name : selection_attribute_names) {
265 const IndexMask changed_element_mask = select_operation(
266 info, elements, attribute_name, memory);
272 attribute_name, selection_domain))
275 selection.span.index_range(), memory);
276 ed::curves::fill_selection_false(selection.span, not_in_mask);
282 if (use_segment_selection) {
285 const IndexRange tree_data_range = tree_data_by_drawing[i_drawing];
286 changed |= ed::greasepencil::apply_mask_as_segment_selection(curves,
287 changed_element_mask,
295 changed |= ed::greasepencil::apply_mask_as_selection(curves,
296 changed_element_mask,
331 *
object,
info, selection_domain, memory);
332 if (selectable_elements.
is_empty()) {
342 info.drawing.strokes_for_write(), selectable_elements, selection_domain, action);
355 ot->
name =
"(De)select All Strokes";
356 ot->
idname =
"GREASE_PENCIL_OT_select_all";
373 ed::greasepencil::selection_update(&vc,
380 info.drawing.strokes(), attribute_name,
false, memory);
394 ot->
idname =
"GREASE_PENCIL_OT_select_more";
409 ed::greasepencil::selection_update(&vc,
416 info.drawing.strokes(), attribute_name,
true, memory);
430 ot->
idname =
"GREASE_PENCIL_OT_select_less";
448 const IndexMask selectable_strokes = ed::greasepencil::retrieve_editable_strokes(
449 *
object,
info.drawing,
info.layer_index, memory);
450 if (selectable_strokes.
is_empty()) {
466 ot->
name =
"Select Linked";
467 ot->
idname =
"GREASE_PENCIL_OT_select_linked";
468 ot->
description =
"Select all points in curves with any point selection";
494 ed::greasepencil::selection_update(
502 *
object,
info, selection_domain, memory);
503 if (selectable_elements.
is_empty()) {
506 return random_mask(selectable_elements,
507 info.drawing.strokes().points_num(),
523 ot->
name =
"Select Random";
524 ot->
idname =
"GREASE_PENCIL_OT_select_random";
525 ot->
description =
"Selects random points from the current strokes selection";
557 ot->
name =
"Select Alternate";
558 ot->
idname =
"GREASE_PENCIL_OT_select_alternate";
559 ot->
description =
"Select alternated points in strokes with already selected points";
570 "(De)select the first and last point of each stroke");
582 {int(SelectSimilarMode::LAYER),
"LAYER", 0,
"Layer",
""},
583 {int(SelectSimilarMode::MATERIAL),
"MATERIAL", 0,
"Material",
""},
584 {int(SelectSimilarMode::VERTEX_COLOR),
"VERTEX_COLOR", 0,
"Vertex Color",
""},
585 {int(SelectSimilarMode::RADIUS),
"RADIUS", 0,
"Radius",
""},
586 {int(SelectSimilarMode::OPACITY),
"OPACITY", 0,
"Opacity",
""},
587 {0,
nullptr, 0,
nullptr,
nullptr},
597 CPPType::get<T>().default_construct(&default_value);
601 ".selection", domain,
true);
603 attribute_id, domain, default_value);
606 threading::parallel_for(
608 Set<T> &local_value_set = value_set_by_thread.local();
609 for (const int i : range) {
611 local_value_set.add(values[i]);
616 for (
const Set<T> &local_value_set : value_set_by_thread) {
618 for (
const T &
key : local_value_set) {
619 r_value_set.add(
key);
624template<
typename T,
typename DistanceFn>
631 DistanceFn distance_fn)
636 CPPType::get<T>().default_construct(&default_value);
644 info.drawing.strokes(), selection_domain, attribute_id, selected_values);
653 attribute_id, selection_domain, default_value);
656 const IndexMask mask = ed::greasepencil::retrieve_editable_points(
657 *
object,
info.drawing,
info.layer_index, memory);
660 if (selection[index]) {
663 for (
const T &test_value : selected_values) {
664 if (distance_fn(values[index], test_value) <= threshold) {
665 selection[index] =
true;
670 selection_writer.
finish();
686 *
info.drawing.strokes().attributes().lookup_or_default<
bool>(
".selection", domain,
true);
689 selected_layers.
add(
info.layer_index);
705 ed::curves::select_all(
706 info.drawing.strokes_for_write(), editable_elements, domain,
SEL_SELECT);
721 case SelectSimilarMode::LAYER:
724 case SelectSimilarMode::MATERIAL:
725 select_similar_by_value<int>(
732 [](
const int a,
const int b) ->
float {
return float(
math::distance(a,
b)); });
734 case SelectSimilarMode::VERTEX_COLOR:
735 select_similar_by_value<ColorGeometry4f>(
746 case SelectSimilarMode::RADIUS:
747 select_similar_by_value<float>(
754 [](
const float a,
const float b) ->
float {
return math::distance(a,
b); });
756 case SelectSimilarMode::OPACITY:
757 select_similar_by_value<float>(
764 [](
const float a,
const float b) ->
float {
return math::distance(a,
b); });
776 ot->
name =
"Select Similar";
777 ot->
idname =
"GREASE_PENCIL_OT_select_similar";
778 ot->
description =
"Select all strokes with similar characteristics";
800 ed::greasepencil::selection_update(
807 const IndexMask selectable_strokes = ed::greasepencil::retrieve_editable_strokes(
808 *
object,
info.drawing,
info.layer_index, memory);
809 return ed::curves::end_points(
810 info.drawing.strokes(), selectable_strokes, amount_start, amount_end,
false, memory);
824 ot->
idname =
"GREASE_PENCIL_OT_select_ends";
838 "Number of points to select from the start",
847 "Number of points to select from the end",
854 bool changed =
false;
876 const std::optional<bke::AttributeMetaData> meta_data = attributes.
lookup_meta_data(
878 if ((!meta_data) || (meta_data->domain == domain)) {
884 if (domain == bke::AttrDomain::Curve) {
889 const GVArray src = *attributes.
lookup(
".selection", domain);
895 attributes.
remove(
".selection");
896 if (!attributes.
add(
".selection",
898 bke::cpp_type_to_custom_data_type(type),
922 bool changed =
false;
957 ot->
description =
"Change the selection mode for Grease Pencil strokes";
976 const int material_index =
object->actcol - 1;
979 if (material_index == -1) {
989 *
object,
info.drawing, material_index, memory);
996 ed::curves::get_curves_selection_attribute_names(curves);
998 for (
const int i : selection_attribute_names.
index_range()) {
1000 curves, domain,
CD_PROP_BOOL, selection_attribute_names[i]);
1002 case bke::AttrDomain::Curve: {
1003 index_mask::masked_fill(selection.
span.
typed<
bool>(),
select, strokes);
1006 case bke::AttrDomain::Point: {
1008 const IndexRange points = points_by_curve[curve_index];
1029 ot->
name =
"Select Material";
1030 ot->
idname =
"GREASE_PENCIL_OT_material_select";
1031 ot->
description =
"Select/Deselect all Grease Pencil strokes using current material";
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ToolSettings * CTX_data_tool_settings(const bContext *C)
Low-level operations for curves.
Low-level operations for grease pencil.
General operations, lookup, etc. for blender objects.
bool BKE_object_is_mode_compat(const Object *ob, eObjectMode object_mode)
#define BLI_assert_unreachable()
#define BLI_SCOPED_DEFER(function_to_defer)
void DEG_id_tag_update(ID *id, unsigned int flags)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ OB_MODE_VERTEX_GREASE_PENCIL
@ OB_MODE_SCULPT_GREASE_PENCIL
Object is a sort of wrapper for general info.
@ GP_SCULPT_MASK_SELECTMODE_POINT
@ GP_SCULPT_MASK_SELECTMODE_STROKE
@ GP_SCULPT_MASK_SELECTMODE_SEGMENT
@ GP_VERTEX_MASK_SELECTMODE_SEGMENT
@ GP_VERTEX_MASK_SELECTMODE_STROKE
@ GP_VERTEX_MASK_SELECTMODE_POINT
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph)
static unsigned long seed
GMutableSpan slice(const int64_t start, int64_t size) const
MutableSpan< T > typed() const
const CPPType & type() const
void materialize(void *dst) const
constexpr int64_t first() const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr bool is_empty() const
static constexpr IndexRange from_begin_end(const int64_t begin, const int64_t end)
static constexpr IndexRange from_begin_end_inclusive(const int64_t begin, const int64_t last)
bool contains(const Key &key) const
constexpr IndexRange index_range() const
GAttributeReader lookup(const StringRef attribute_id) const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
int domain_size(const AttrDomain domain) const
std::optional< AttributeMetaData > lookup_meta_data(StringRef attribute_id) const
OffsetIndices< int > points_by_curve() const
MutableAttributeAccessor attributes_for_write()
AttributeAccessor attributes() const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool remove(const StringRef attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
void to_bools(MutableSpan< bool > r_bools) const
void foreach_index(Fn &&fn) const
IndexRange index_range() const
static wmOperatorStatus select_linked_exec(bContext *C, wmOperator *)
VecBase< float, 4 > float4
blender::bke::AttrDomain ED_grease_pencil_sculpt_selection_domain_get(const ToolSettings *tool_settings)
bool ED_grease_pencil_sculpt_segment_selection_enabled(const ToolSettings *tool_settings)
blender::bke::AttrDomain ED_grease_pencil_edit_selection_domain_get(const ToolSettings *tool_settings)
bool ED_grease_pencil_edit_segment_selection_enabled(const ToolSettings *tool_settings)
blender::bke::AttrDomain ED_grease_pencil_vertex_selection_domain_get(const ToolSettings *tool_settings)
void ED_operatortypes_grease_pencil_select()
blender::bke::AttrDomain ED_grease_pencil_selection_domain_get(const ToolSettings *tool_settings, const Object *object)
bool ED_grease_pencil_segment_selection_enabled(const ToolSettings *tool_settings, const Object *object)
bool ED_grease_pencil_vertex_segment_selection_enabled(const ToolSettings *tool_settings)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
static wmOperatorStatus select_all_exec(bContext *C, wmOperator *op)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void select_linked(bke::CurvesGeometry &curves, const IndexMask &curves_mask)
void apply_selection_operation_at_index(GMutableSpan selection, const int index, const eSelectOp sel_op)
static bool has_anything_selected(const Span< Curves * > curves_ids)
void select_all(bke::CurvesGeometry &curves, const IndexMask &mask, const bke::AttrDomain selection_domain, int action)
void select_alternate(bke::CurvesGeometry &curves, const IndexMask &curves_mask, const bool deselect_ends)
IndexMask curve_mask_from_points(const bke::CurvesGeometry &curves, const IndexMask &point_mask, const GrainSize grain_size, IndexMaskMemory &memory)
IndexMask select_adjacent_mask(const bke::CurvesGeometry &curves, const IndexMask &curves_mask, const StringRef attribute_name, const bool deselect, IndexMaskMemory &memory)
bke::GSpanAttributeWriter ensure_selection_attribute(bke::CurvesGeometry &curves, bke::AttrDomain selection_domain, eCustomDataType create_type, StringRef attribute_name)
static void GREASE_PENCIL_OT_select_linked(wmOperatorType *ot)
static void select_similar_by_value(Scene *scene, Object *object, GreasePencil &grease_pencil, const bke::AttrDomain selection_domain, const StringRef attribute_id, float threshold, DistanceFn distance_fn)
static wmOperatorStatus select_ends_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_select_more(wmOperatorType *ot)
static wmOperatorStatus select_set_mode_exec(bContext *C, wmOperator *op)
bool selection_update(const ViewContext *vc, const eSelectOp sel_op, SelectionUpdateFunc select_operation)
bool ensure_selection_domain(ToolSettings *ts, Object *object)
bool editable_grease_pencil_point_selection_poll(bContext *C)
IndexMask retrieve_editable_elements(Object &object, const MutableDrawingInfo &info, const bke::AttrDomain selection_domain, IndexMaskMemory &memory)
static const EnumPropertyItem select_similar_mode_items[]
CurveSegmentsData find_curve_segments(const bke::CurvesGeometry &curves, const IndexMask &curve_mask, const Span< float2 > screen_space_positions, const Curves2DBVHTree &tree_data, const IndexRange tree_data_range)
static wmOperatorStatus select_alternate_exec(bContext *C, wmOperator *op)
static void select_similar_by_layer(Scene *scene, Object *object, GreasePencil &grease_pencil, bke::AttrDomain domain)
IndexMask retrieve_editable_strokes_by_material(Object &object, const bke::greasepencil::Drawing &drawing, const int mat_i, IndexMaskMemory &memory)
int clamp_range(const IndexRange range, const int index)
bool editable_grease_pencil_poll(bContext *C)
static wmOperatorStatus select_similar_exec(bContext *C, wmOperator *op)
static int foreach_curve_segment(const CurveSegmentsData &segment_data, const int curve_index, const IndexRange points, Fn &&fn)
static void GREASE_PENCIL_OT_select_less(wmOperatorType *ot)
void insert_selected_values(const bke::CurvesGeometry &curves, const bke::AttrDomain domain, const StringRef attribute_id, blender::Set< T > &r_value_set)
bool apply_mask_as_selection(bke::CurvesGeometry &curves, const IndexMask &selection_mask, const bke::AttrDomain selection_domain, const StringRef attribute_name, const GrainSize grain_size, const eSelectOp sel_op)
static void GREASE_PENCIL_OT_select_all(wmOperatorType *ot)
static void GREASE_PENCIL_OT_select_alternate(wmOperatorType *ot)
static void GREASE_PENCIL_OT_select_ends(wmOperatorType *ot)
static void GREASE_PENCIL_OT_select_similar(wmOperatorType *ot)
Vector< MutableDrawingInfo > retrieve_editable_drawings(const Scene &scene, GreasePencil &grease_pencil)
static void GREASE_PENCIL_OT_select_random(wmOperatorType *ot)
static wmOperatorStatus grease_pencil_material_select_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_material_select(wmOperatorType *ot)
static void GREASE_PENCIL_OT_set_selection_mode(wmOperatorType *ot)
bool apply_mask_as_segment_selection(bke::CurvesGeometry &curves, const IndexMask &point_selection_mask, const StringRef attribute_name, const Curves2DBVHTree &tree_data, const IndexRange tree_data_range, const GrainSize grain_size, const eSelectOp sel_op)
T distance(const T &a, const T &b)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
uint64_t get_default_hash(const T &v, const Args &...args)
static wmOperatorStatus select_random_exec(bContext *C, wmOperator *op)
static wmOperatorStatus select_less_exec(bContext *C, wmOperator *)
static wmOperatorStatus select_more_exec(bContext *C, wmOperator *)
int RNA_int_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
const EnumPropertyItem rna_enum_grease_pencil_selectmode_items[]
struct ToolSettings * toolsettings
Array< int > segment_offsets
Array< int > segment_start_points
Array< float > segment_start_fractions
Array< int > drawing_offsets
Array< float2 > start_positions
wmOperatorStatus(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
wmOperatorStatus(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
int WM_operator_properties_select_random_seed_increment_get(wmOperator *op)
void WM_operator_properties_select_random(wmOperatorType *ot)
void WM_operator_properties_select_all(wmOperatorType *ot)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)