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()) {
162 curves, changed_curve_mask, screen_space_positions, tree_data, tree_data_range);
171 point_selection_mask.
to_bools(changed_points);
173 auto test_points_range = [&](
const IndexRange range) ->
bool {
174 for (
const int point_i : range) {
175 if (changed_points[point_i]) {
181 auto update_points_range = [&](
const IndexRange range) {
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;
234 if (drawings.is_empty()) {
237 const int frame_number = drawings.first().frame_number;
242 if (use_segment_selection) {
244 *vc, *ob_eval, grease_pencil, drawings, frame_number);
248 for (
const int i_drawing : drawings.index_range()) {
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);
271 curves.attributes_for_write().lookup_or_add_for_write_span<
bool>(
272 attribute_name, selection_domain))
275 selection.span.index_range(), memory);
282 if (use_segment_selection) {
285 const IndexRange tree_data_range = tree_data_by_drawing[i_drawing];
287 changed_element_mask,
296 changed_element_mask,
331 *
object, info, selection_domain, memory);
332 if (selectable_elements.
is_empty()) {
355 ot->name =
"(De)select All Strokes";
356 ot->idname =
"GREASE_PENCIL_OT_select_all";
357 ot->description =
"(De)select all visible strokes";
393 ot->name =
"Select More";
394 ot->idname =
"GREASE_PENCIL_OT_select_more";
395 ot->description =
"Grow the selection by one point";
429 ot->name =
"Select Less";
430 ot->idname =
"GREASE_PENCIL_OT_select_less";
431 ot->description =
"Shrink the selection by one point";
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";
502 *
object, info, selection_domain, memory);
503 if (selectable_elements.
is_empty()) {
506 return random_mask(selectable_elements,
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");
587 {0,
nullptr, 0,
nullptr,
nullptr},
601 ".selection", domain,
true);
603 attribute_id, domain, default_value);
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)
644 info.drawing.strokes(), selection_domain, attribute_id, selected_values);
653 attribute_id, selection_domain, default_value);
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);
732 [](
const int a,
const int b) ->
float {
return float(
math::distance(a,
b)); });
754 [](
const float a,
const float b) ->
float {
return math::distance(a,
b); });
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";
810 info.
drawing.
strokes(), selectable_strokes, amount_start, amount_end,
false, memory);
823 ot->name =
"Select Ends";
824 ot->idname =
"GREASE_PENCIL_OT_select_ends";
825 ot->description =
"Select end points of strokes";
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)) {
889 const GVArray src = *attributes.
lookup(
".selection", domain);
895 attributes.
remove(
".selection");
896 if (!attributes.
add(
".selection",
922 bool changed =
false;
955 ot->name =
"Select Mode";
956 ot->idname = __func__;
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);
998 for (
const int i : selection_attribute_names.
index_range()) {
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
static const CPPType & get()
void default_construct(void *ptr) const
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
bool remove(const StringRef attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
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)
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
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)
void fill_selection_false(GMutableSpan selection)
IndexMask select_adjacent_mask(const bke::CurvesGeometry &curves, const IndexMask &curves_mask, const StringRef attribute_name, const bool deselect, IndexMaskMemory &memory)
Span< StringRef > get_curves_selection_attribute_names(const bke::CurvesGeometry &curves)
void fill_selection(GMutableSpan selection, bool value)
IndexMask end_points(const bke::CurvesGeometry &curves, const IndexMask &curves_mask, const int amount_start, const int amount_end, const bool inverted, 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)
IndexMask retrieve_editable_points(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, IndexMaskMemory &memory)
FunctionRef< IndexMask(const ed::greasepencil::MutableDrawingInfo &info, const IndexMask &universe, StringRef attribute_name, IndexMaskMemory &memory)> SelectionUpdateFunc
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)
static wmOperatorStatus select_more_exec(bContext *C, wmOperator *)
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)
void free_curves_2d_bvh_data(Curves2DBVHTree &data)
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)
static wmOperatorStatus select_all_exec(bContext *C, wmOperator *op)
static wmOperatorStatus select_random_exec(bContext *C, wmOperator *op)
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)
IndexMask retrieve_editable_strokes(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, IndexMaskMemory &memory)
static wmOperatorStatus select_less_exec(bContext *C, wmOperator *)
Vector< MutableDrawingInfo > retrieve_editable_drawings(const Scene &scene, GreasePencil &grease_pencil)
Curves2DBVHTree build_curves_2d_bvh_from_visible(const ViewContext &vc, const Object &object, const GreasePencil &grease_pencil, Span< MutableDrawingInfo > drawings, const int frame_number)
static wmOperatorStatus select_linked_exec(bContext *C, wmOperator *)
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)
Array< Vector< MutableDrawingInfo > > retrieve_editable_drawings_grouped_per_frame(const Scene &scene, GreasePencil &grease_pencil)
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)
void masked_fill(MutableSpan< T > data, const T &value, const IndexMask &mask)
T distance(const T &a, const T &b)
void parallel_for_each(Range &&range, const Function &function)
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)
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
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
bke::greasepencil::Drawing & drawing
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 *)