53 {0,
nullptr, 0,
nullptr,
nullptr},
58 {
SIMVERT_FACE,
"VERT_FACES", 0,
"Amount of Adjacent Faces",
""},
60 {
SIMVERT_EDGE,
"VERT_EDGES", 0,
"Amount of Connecting Edges",
""},
65 {
SIMEDGE_FACE,
"EDGE_FACES", 0,
"Amount of Faces Around an Edge",
""},
86 {0,
nullptr, 0,
nullptr,
nullptr},
139 float normal[3], co[3];
158 const float thresh_radians = thresh *
float(
M_PI);
161 int tot_faces_selected_all = 0;
165 for (
Object *ob : objects) {
170 if (tot_faces_selected_all == 0) {
175 KDTree_1d *tree_1d =
nullptr;
176 KDTree_3d *tree_3d =
nullptr;
177 KDTree_4d *tree_4d =
nullptr;
178 GSet *gset =
nullptr;
184 tree_1d = BLI_kdtree_1d_new(tot_faces_selected_all);
187 tree_3d = BLI_kdtree_3d_new(tot_faces_selected_all);
190 tree_4d = BLI_kdtree_4d_new(tot_faces_selected_all);
199 for (
Object *ob : objects) {
202 Material ***material_array =
nullptr;
203 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
210 copy_m3_m4(ob_m3, ob->object_to_world().ptr());
214 if (ob->totcol == 0) {
239 Material *material = (*material_array)[face->mat_nr];
240 if (material !=
nullptr) {
247 BLI_kdtree_1d_insert(tree_1d, tree_index++, &area);
252 BLI_kdtree_1d_insert(tree_1d, tree_index++, &perimeter);
260 BLI_kdtree_3d_insert(tree_3d, tree_index++, normal);
266 BLI_kdtree_4d_insert(tree_4d, tree_index++, plane);
271 goto face_select_all;
286 goto face_select_all;
297 if (tree_1d !=
nullptr) {
298 BLI_kdtree_1d_deduplicate(tree_1d);
299 BLI_kdtree_1d_balance(tree_1d);
301 if (tree_3d !=
nullptr) {
302 BLI_kdtree_3d_deduplicate(tree_3d);
303 BLI_kdtree_3d_balance(tree_3d);
305 if (tree_4d !=
nullptr) {
306 BLI_kdtree_4d_deduplicate(tree_4d);
307 BLI_kdtree_4d_balance(tree_4d);
310 for (
Object *ob : objects) {
313 bool changed =
false;
314 Material ***material_array =
nullptr;
317 copy_m3_m4(ob_m3, ob->object_to_world().ptr());
319 bool has_custom_data_layer =
false;
322 if (ob->totcol == 0) {
345 const int num_sides = face->len;
349 const int delta_i = num_sides - num_sides_iter;
358 const Material *material = (*material_array)[face->mat_nr];
359 if (material ==
nullptr) {
367 if (material == material_iter) {
399 KDTreeNearest_3d nearest;
400 if (BLI_kdtree_3d_find_nearest(tree_3d, normal, &nearest) != -1) {
411 KDTreeNearest_4d nearest;
412 if (BLI_kdtree_4d_find_nearest(tree_4d, plane, &nearest) != -1) {
413 if (nearest.dist <= thresh) {
414 if ((
fabsf(plane[3] - nearest.co[3]) <= thresh) &&
415 (
angle_v3v3(plane, nearest.co) <= thresh_radians))
433 if (!has_custom_data_layer) {
460 params.calc_looptris =
false;
461 params.calc_normals =
false;
462 params.is_destructive =
false;
471 for (
Object *ob : objects) {
485 params.calc_looptris =
false;
486 params.calc_normals =
false;
487 params.is_destructive =
false;
492 BLI_kdtree_1d_free(tree_1d);
493 BLI_kdtree_3d_free(tree_3d);
494 BLI_kdtree_4d_free(tree_4d);
495 if (gset !=
nullptr) {
514 mul_m4_v3(ob->object_to_world().ptr(), v1);
565 const float thresh_radians = thresh *
float(
M_PI) + FLT_EPSILON;
568 int tot_edges_selected_all = 0;
572 for (
Object *ob : objects) {
577 if (tot_edges_selected_all == 0) {
582 KDTree_1d *tree_1d =
nullptr;
583 KDTree_3d *tree_3d =
nullptr;
584 GSet *gset =
nullptr;
592 tree_1d = BLI_kdtree_1d_new(tot_edges_selected_all);
595 tree_3d = BLI_kdtree_3d_new(tot_edges_selected_all * 2);
603 for (
Object *ob : objects) {
622 BLI_kdtree_1d_insert(tree_1d, tree_index++, &
pos);
630 BLI_kdtree_1d_insert(tree_1d, tree_index++, &
pos);
637 int custom_data_offset;
648 float ob_m3[3][3], ob_m3_inv[3][3];
649 copy_m3_m4(ob_m3, ob->object_to_world().ptr());
662 float dir[3], dir_flip[3];
664 BLI_kdtree_3d_insert(tree_3d, tree_index++, dir);
668 BLI_kdtree_3d_insert(tree_3d, tree_index++, dir_flip);
673 BLI_kdtree_1d_insert(tree_1d, tree_index++, &length);
679 BLI_kdtree_1d_insert(tree_1d, tree_index++, &angle);
685 goto edge_select_all;
690 goto edge_select_all;
704 goto edge_select_all;
711 BLI_kdtree_1d_insert(tree_1d, tree_index++, value);
721 if (tree_1d !=
nullptr) {
722 BLI_kdtree_1d_deduplicate(tree_1d);
723 BLI_kdtree_1d_balance(tree_1d);
725 if (tree_3d !=
nullptr) {
726 BLI_kdtree_3d_deduplicate(tree_3d);
727 BLI_kdtree_3d_balance(tree_3d);
730 for (
Object *ob : objects) {
733 bool changed =
false;
735 bool has_custom_data_layer =
false;
747 if (!has_custom_data_layer) {
760 if (!has_custom_data_layer) {
772 float ob_m3[3][3], ob_m3_inv[3][3];
773 copy_m3_m4(ob_m3, ob->object_to_world().ptr());
776 int custom_data_offset;
799 const int delta_i = num_faces - num_faces_iter;
813 KDTreeNearest_3d nearest;
814 if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
856 if (!has_custom_data_layer) {
873 if (!has_custom_data_layer) {
898 params.calc_looptris =
false;
899 params.calc_normals =
false;
900 params.is_destructive =
false;
909 for (
Object *ob : objects) {
923 params.calc_looptris =
false;
924 params.calc_normals =
false;
925 params.is_destructive =
false;
930 BLI_kdtree_1d_free(tree_1d);
931 BLI_kdtree_3d_free(tree_3d);
932 if (gset !=
nullptr) {
953 const float thresh_radians = thresh *
float(
M_PI) + FLT_EPSILON;
956 int tot_verts_selected_all = 0;
960 for (
Object *ob : objects) {
965 if (tot_verts_selected_all == 0) {
970 KDTree_3d *tree_3d =
nullptr;
971 KDTree_1d *tree_1d =
nullptr;
972 GSet *gset =
nullptr;
976 tree_3d = BLI_kdtree_3d_new(tot_verts_selected_all);
979 tree_1d = BLI_kdtree_1d_new(tot_verts_selected_all);
990 int normal_tree_index = 0;
991 int tree_1d_index = 0;
992 for (
Object *ob : objects) {
995 int cd_dvert_offset = -1;
996 int cd_crease_offset = -1;
1000 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
1008 if (cd_dvert_offset == -1) {
1012 if (defbase_len == 0) {
1020 BLI_kdtree_1d_insert(tree_1d, tree_1d_index++, &
pos);
1044 BLI_kdtree_3d_insert(tree_3d, normal_tree_index++, normal);
1052 for (
int i = 0; i < dvert->
totweight; i++, dw++) {
1063 BLI_kdtree_1d_insert(tree_1d, tree_1d_index++, value);
1094 if (tree_1d !=
nullptr) {
1095 BLI_kdtree_1d_deduplicate(tree_1d);
1096 BLI_kdtree_1d_balance(tree_1d);
1098 if (tree_3d !=
nullptr) {
1099 BLI_kdtree_3d_deduplicate(tree_3d);
1100 BLI_kdtree_3d_balance(tree_3d);
1104 for (
Object *ob : objects) {
1107 bool changed =
false;
1108 bool has_crease_layer =
false;
1109 int cd_dvert_offset = -1;
1110 int cd_crease_offset = -1;
1112 int defbase_len = 0;
1116 if (cd_dvert_offset == -1) {
1121 if (defbase_len == 0) {
1129 bool found_any =
false;
1134 if (vgroup_id != -1) {
1139 if (found_any ==
false) {
1147 if (!has_crease_layer) {
1169 const int delta_i = num_edges - num_edges_iter;
1182 const int delta_i = num_faces - num_faces_iter;
1198 KDTreeNearest_3d nearest;
1199 if (BLI_kdtree_3d_find_nearest(tree_3d, normal, &nearest) != -1) {
1211 for (
int i = 0; i < dvert->
totweight; i++, dw++) {
1224 if (!has_crease_layer) {
1252 params.calc_looptris =
false;
1253 params.calc_normals =
false;
1254 params.is_destructive =
false;
1259 BLI_kdtree_1d_free(tree_1d);
1260 BLI_kdtree_3d_free(tree_3d);
1261 if (gset !=
nullptr) {
1326#ifdef WITH_FREESTYLE
1353 if (
STREQ(prop_id,
"compare")) {
1359 else if (
STREQ(prop_id,
"threshold")) {
1384 ot->
name =
"Select Similar";
1385 ot->
idname =
"MESH_OT_select_similar";
1386 ot->
description =
"Select similar vertices, edges or faces by property types";
1404 prop =
RNA_def_float(
ot->
srna,
"threshold", 0.0f, 0.0f, 1.0f,
"Threshold",
"", 0.0f, 1.0f);
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
ToolSettings * CTX_data_tool_settings(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
bool CustomData_has_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
void * CustomData_bmesh_get(const CustomData *data, void *block, eCustomDataType type)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode_unique_data(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
General operations, lookup, etc. for materials.
struct Material *** BKE_object_material_array_p(struct Object *ob)
void BKE_report(ReportList *reports, eReportType type, const char *message)
#define BLI_BITMAP_NEW(_num, _alloc_string)
#define BLI_BITMAP_TEST(_bitmap, _index)
#define BLI_BITMAP_ENABLE(_bitmap, _index)
GSet * BLI_gset_ptr_new(const char *info)
GSet * BLI_gset_str_new(const char *info)
unsigned int BLI_gset_len(const GSet *gs) ATTR_WARN_UNUSED_RESULT
BLI_INLINE void * BLI_gsetIterator_getKey(GSetIterator *gsi)
#define GSET_ITER(gs_iter_, gset_)
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
bool BLI_gset_add(GSet *gs, void *key)
A KD-tree for nearest neighbor search.
#define LISTBASE_FOREACH(type, var, list)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void mul_m4_v3(const float M[4][4], float r[3])
void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3])
float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float n[3])
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define BLT_I18NCONTEXT_ID_MESH
void EDBM_update(Mesh *mesh, const EDBMUpdate_Params *params)
void EDBM_selectmode_flush(BMEditMesh *em)
bool ED_operator_editmesh(bContext *C)
bool ED_select_similar_compare_float_tree(const KDTree_1d *tree, float length, float thresh, eSimilarCmp compare)
Read Guarded memory(de)allocation.
#define BM_FACE_FIRST_LOOP(p)
#define BM_ELEM_CD_GET_FLOAT_P(ele, offset)
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
Select Face.
void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select)
Select Vert.
void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
Select Edge.
float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3])
float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3])
int BM_edge_face_count_at_most(const BMEdge *e, const int count_max)
int BM_vert_face_count(const BMVert *v)
int BM_edge_face_count(const BMEdge *e)
int BM_vert_edge_count(const BMVert *v)
float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3])
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static int edbm_select_similar_exec(bContext *C, wmOperator *op)
static int mesh_select_similar_compare_int(const int delta, const int compare)
static int similar_edge_select_exec(bContext *C, wmOperator *op)
static int similar_vert_select_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_similar_types[]
static bool edbm_select_similar_poll_property(const bContext *, wmOperator *op, const PropertyRNA *prop)
static bool edge_data_value_set(BMEdge *edge, const int hflag, int *r_value)
static const EnumPropertyItem * select_similar_type_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
void MESH_OT_select_similar(wmOperatorType *ot)
static float edge_length_squared_worldspace_get(Object *ob, BMEdge *edge)
static int similar_face_select_exec(bContext *C, wmOperator *op)
static void face_to_plane(const Object *ob, BMFace *face, float r_plane[4])
static void edge_pos_direction_worldspace_get(Object *ob, BMEdge *edge, float *r_dir)
static const EnumPropertyItem prop_similar_compare_types[]
static bool face_data_value_set(BMFace *face, const int hflag, int *r_value)
draw_view in_light_buf[] float
void MEM_freeN(void *vmemh)
ccl_device_inline float4 select(const int4 mask, const float4 a, const float4 b)
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
int RNA_enum_get(PointerRNA *ptr, const char *name)
const char * RNA_property_identifier(const PropertyRNA *prop)
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)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
void RNA_enum_items_add_value(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item, int value)
void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double step, int precision)
bool(* poll_property)(const bContext *C, wmOperator *op, const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
struct ReportList * reports
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)