54 {0,
nullptr, 0,
nullptr,
nullptr},
59 {
SIMVERT_FACE,
"VERT_FACES", 0,
"Amount of Adjacent Faces",
""},
61 {
SIMVERT_EDGE,
"VERT_EDGES", 0,
"Amount of Connecting Edges",
""},
66 {
SIMEDGE_FACE,
"EDGE_FACES", 0,
"Amount of Faces Around an Edge",
""},
87 {0,
nullptr, 0,
nullptr,
nullptr},
140 float normal[3], co[3];
159 const float thresh_radians = thresh * float(
M_PI);
162 int tot_faces_selected_all = 0;
166 for (
Object *ob : objects) {
171 if (tot_faces_selected_all == 0) {
176 KDTree_1d *tree_1d =
nullptr;
177 KDTree_3d *tree_3d =
nullptr;
178 KDTree_4d *tree_4d =
nullptr;
179 GSet *gset =
nullptr;
185 tree_1d = BLI_kdtree_1d_new(tot_faces_selected_all);
188 tree_3d = BLI_kdtree_3d_new(tot_faces_selected_all);
191 tree_4d = BLI_kdtree_4d_new(tot_faces_selected_all);
200 for (
Object *ob : objects) {
203 Material ***material_array =
nullptr;
204 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
206 if (
bm->totfacesel == 0) {
211 copy_m3_m4(ob_m3, ob->object_to_world().ptr());
215 if (ob->totcol == 0) {
241 if (material !=
nullptr) {
248 BLI_kdtree_1d_insert(tree_1d, tree_index++, &area);
253 BLI_kdtree_1d_insert(tree_1d, tree_index++, &perimeter);
261 BLI_kdtree_3d_insert(tree_3d, tree_index++, normal);
267 BLI_kdtree_4d_insert(tree_4d, tree_index++, plane);
272 goto face_select_all;
287 goto face_select_all;
298 if (tree_1d !=
nullptr) {
299 BLI_kdtree_1d_deduplicate(tree_1d);
300 BLI_kdtree_1d_balance(tree_1d);
302 if (tree_3d !=
nullptr) {
303 BLI_kdtree_3d_deduplicate(tree_3d);
304 BLI_kdtree_3d_balance(tree_3d);
306 if (tree_4d !=
nullptr) {
307 BLI_kdtree_4d_deduplicate(tree_4d);
308 BLI_kdtree_4d_balance(tree_4d);
311 for (
Object *ob : objects) {
314 bool changed =
false;
315 Material ***material_array =
nullptr;
318 copy_m3_m4(ob_m3, ob->object_to_world().ptr());
320 bool has_custom_data_layer =
false;
323 if (ob->totcol == 0) {
346 const int num_sides = face->
len;
350 const int delta_i = num_sides - num_sides_iter;
360 if (material ==
nullptr) {
368 if (material == material_iter) {
400 KDTreeNearest_3d nearest;
401 if (BLI_kdtree_3d_find_nearest(tree_3d, normal, &nearest) != -1) {
412 KDTreeNearest_4d nearest;
413 if (BLI_kdtree_4d_find_nearest(tree_4d, plane, &nearest) != -1) {
414 if (nearest.dist <= thresh) {
415 if ((
fabsf(plane[3] - nearest.co[3]) <= thresh) &&
416 (
angle_v3v3(plane, nearest.co) <= thresh_radians))
434 if (!has_custom_data_layer) {
461 params.calc_looptris =
false;
462 params.calc_normals =
false;
463 params.is_destructive =
false;
472 for (
Object *ob : objects) {
486 params.calc_looptris =
false;
487 params.calc_normals =
false;
488 params.is_destructive =
false;
493 BLI_kdtree_1d_free(tree_1d);
494 BLI_kdtree_3d_free(tree_3d);
495 BLI_kdtree_4d_free(tree_4d);
496 if (gset !=
nullptr) {
515 mul_m4_v3(ob->object_to_world().ptr(), v1);
566 const float thresh_radians = thresh * float(
M_PI) + FLT_EPSILON;
569 int tot_edges_selected_all = 0;
573 for (
Object *ob : objects) {
578 if (tot_edges_selected_all == 0) {
583 KDTree_1d *tree_1d =
nullptr;
584 KDTree_3d *tree_3d =
nullptr;
585 GSet *gset =
nullptr;
593 tree_1d = BLI_kdtree_1d_new(tot_edges_selected_all);
596 tree_3d = BLI_kdtree_3d_new(tot_edges_selected_all * 2);
604 for (
Object *ob : objects) {
608 if (
bm->totedgesel == 0) {
623 BLI_kdtree_1d_insert(tree_1d, tree_index++, &
pos);
631 BLI_kdtree_1d_insert(tree_1d, tree_index++, &
pos);
638 int custom_data_offset;
649 float ob_m3[3][3], ob_m3_inv[3][3];
650 copy_m3_m4(ob_m3, ob->object_to_world().ptr());
663 float dir[3], dir_flip[3];
665 BLI_kdtree_3d_insert(tree_3d, tree_index++, dir);
669 BLI_kdtree_3d_insert(tree_3d, tree_index++, dir_flip);
674 BLI_kdtree_1d_insert(tree_1d, tree_index++, &
length);
680 BLI_kdtree_1d_insert(tree_1d, tree_index++, &
angle);
686 goto edge_select_all;
691 goto edge_select_all;
705 goto edge_select_all;
712 BLI_kdtree_1d_insert(tree_1d, tree_index++, value);
722 if (tree_1d !=
nullptr) {
723 BLI_kdtree_1d_deduplicate(tree_1d);
724 BLI_kdtree_1d_balance(tree_1d);
726 if (tree_3d !=
nullptr) {
727 BLI_kdtree_3d_deduplicate(tree_3d);
728 BLI_kdtree_3d_balance(tree_3d);
731 for (
Object *ob : objects) {
734 bool changed =
false;
736 bool has_custom_data_layer =
false;
748 if (!has_custom_data_layer) {
761 if (!has_custom_data_layer) {
773 float ob_m3[3][3], ob_m3_inv[3][3];
774 copy_m3_m4(ob_m3, ob->object_to_world().ptr());
777 int custom_data_offset;
800 const int delta_i = num_faces - num_faces_iter;
814 KDTreeNearest_3d nearest;
815 if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
857 if (!has_custom_data_layer) {
874 if (!has_custom_data_layer) {
899 params.calc_looptris =
false;
900 params.calc_normals =
false;
901 params.is_destructive =
false;
910 for (
Object *ob : objects) {
924 params.calc_looptris =
false;
925 params.calc_normals =
false;
926 params.is_destructive =
false;
931 BLI_kdtree_1d_free(tree_1d);
932 BLI_kdtree_3d_free(tree_3d);
933 if (gset !=
nullptr) {
954 const float thresh_radians = thresh * float(
M_PI) + FLT_EPSILON;
957 int tot_verts_selected_all = 0;
961 for (
Object *ob : objects) {
966 if (tot_verts_selected_all == 0) {
971 KDTree_3d *tree_3d =
nullptr;
972 KDTree_1d *tree_1d =
nullptr;
978 tree_3d = BLI_kdtree_3d_new(tot_verts_selected_all);
981 tree_1d = BLI_kdtree_1d_new(tot_verts_selected_all);
989 int normal_tree_index = 0;
990 int tree_1d_index = 0;
991 for (
Object *ob : objects) {
994 int cd_dvert_offset = -1;
995 int cd_crease_offset = -1;
999 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
1001 if (
bm->totvertsel == 0) {
1007 if (cd_dvert_offset == -1) {
1011 if (defbase_len == 0) {
1019 BLI_kdtree_1d_insert(tree_1d, tree_1d_index++, &
pos);
1043 BLI_kdtree_3d_insert(tree_3d, normal_tree_index++, normal);
1062 BLI_kdtree_1d_insert(tree_1d, tree_1d_index++, value);
1078 selected_vertex_groups.
add_as(dg->name);
1087 if (selected_vertex_groups.
is_empty()) {
1093 if (tree_1d !=
nullptr) {
1094 BLI_kdtree_1d_deduplicate(tree_1d);
1095 BLI_kdtree_1d_balance(tree_1d);
1097 if (tree_3d !=
nullptr) {
1098 BLI_kdtree_3d_deduplicate(tree_3d);
1099 BLI_kdtree_3d_balance(tree_3d);
1103 for (
Object *ob : objects) {
1106 bool changed =
false;
1107 bool has_crease_layer =
false;
1108 int cd_dvert_offset = -1;
1109 int cd_crease_offset = -1;
1111 int defbase_len = 0;
1115 if (cd_dvert_offset == -1) {
1120 if (defbase_len == 0) {
1128 bool found_any =
false;
1131 if (vgroup_id != -1) {
1136 if (found_any ==
false) {
1144 if (!has_crease_layer) {
1163 for (
const int num_edges_iter : connected_elems_num_set) {
1164 const int delta_i = num_edges - num_edges_iter;
1174 for (
const int num_faces_iter : connected_elems_num_set) {
1175 const int delta_i = num_faces - num_faces_iter;
1191 KDTreeNearest_3d nearest;
1192 if (BLI_kdtree_3d_find_nearest(tree_3d, normal, &nearest) != -1) {
1217 if (!has_crease_layer) {
1245 params.calc_looptris =
false;
1246 params.calc_normals =
false;
1247 params.is_destructive =
false;
1252 BLI_kdtree_1d_free(tree_1d);
1253 BLI_kdtree_3d_free(tree_3d);
1316#ifdef WITH_FREESTYLE
1343 if (
STREQ(prop_id,
"compare")) {
1349 else if (
STREQ(prop_id,
"threshold")) {
1374 ot->name =
"Select Similar";
1375 ot->idname =
"MESH_OT_select_similar";
1376 ot->description =
"Select similar vertices, edges or faces by property types";
1394 prop =
RNA_def_float(
ot->srna,
"threshold", 0.0f, 0.0f, 100000.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.
Material *** BKE_object_material_array_p(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)
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 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)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Read Guarded memory(de)allocation.
static const EnumPropertyItem prop_similar_types[]
#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)
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
bool add_as(ForwardKey &&key)
static int mesh_select_similar_compare_int(const int delta, const int compare)
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 wmOperatorStatus edbm_select_similar_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 wmOperatorStatus similar_face_select_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_similar_compare_types[]
static wmOperatorStatus similar_edge_select_exec(bContext *C, wmOperator *op)
static wmOperatorStatus similar_vert_select_exec(bContext *C, wmOperator *op)
static bool face_data_value_set(BMFace *face, const int hflag, int *r_value)
float length(VecOp< float, D >) RET
void MEM_freeN(void *vmemh)
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)
struct ReportList * reports
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)