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());
213 int custom_data_offset = -1;
216 if (ob->totcol == 0) {
225 if (custom_data_offset == -1) {
244 if (material !=
nullptr) {
251 BLI_kdtree_1d_insert(tree_1d, tree_index++, &area);
256 BLI_kdtree_1d_insert(tree_1d, tree_index++, &perimeter);
264 BLI_kdtree_3d_insert(tree_3d, tree_index++, normal);
270 BLI_kdtree_4d_insert(tree_4d, tree_index++, plane);
275 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 int custom_data_offset = -1;
323 if (ob->totcol == 0) {
347 const int num_sides = face->
len;
351 const int delta_i = num_sides - num_sides_iter;
361 if (material ==
nullptr) {
369 if (material == material_iter) {
401 KDTreeNearest_3d nearest;
402 if (BLI_kdtree_3d_find_nearest(tree_3d, normal, &nearest) != -1) {
413 KDTreeNearest_4d nearest;
414 if (BLI_kdtree_4d_find_nearest(tree_4d, plane, &nearest) != -1) {
415 if (nearest.dist <= thresh) {
416 if ((
fabsf(plane[3] - nearest.co[3]) <= thresh) &&
417 (
angle_v3v3(plane, nearest.co) <= thresh_radians))
434 if (custom_data_offset == -1) {
460 params.calc_looptris =
false;
461 params.calc_normals =
false;
462 params.is_destructive =
false;
471 for (
Object *ob : objects) {
487 params.calc_looptris =
false;
488 params.calc_normals =
false;
489 params.is_destructive =
false;
494 BLI_kdtree_1d_free(tree_1d);
495 BLI_kdtree_3d_free(tree_3d);
496 BLI_kdtree_4d_free(tree_4d);
497 if (gset !=
nullptr) {
516 mul_m4_v3(ob->object_to_world().ptr(), v1);
567 const float thresh_radians = thresh *
float(
M_PI) + FLT_EPSILON;
570 int tot_edges_selected_all = 0;
574 for (
Object *ob : objects) {
579 if (tot_edges_selected_all == 0) {
584 KDTree_1d *tree_1d =
nullptr;
585 KDTree_3d *tree_3d =
nullptr;
586 GSet *gset =
nullptr;
594 tree_1d = BLI_kdtree_1d_new(tot_edges_selected_all);
597 tree_3d = BLI_kdtree_3d_new(tot_edges_selected_all * 2);
605 for (
Object *ob : objects) {
609 if (
bm->totedgesel == 0) {
624 BLI_kdtree_1d_insert(tree_1d, tree_index++, &
pos);
632 BLI_kdtree_1d_insert(tree_1d, tree_index++, &
pos);
639 int custom_data_offset;
655 float ob_m3[3][3], ob_m3_inv[3][3];
656 copy_m3_m4(ob_m3, ob->object_to_world().ptr());
669 float dir[3], dir_flip[3];
671 BLI_kdtree_3d_insert(tree_3d, tree_index++, dir);
675 BLI_kdtree_3d_insert(tree_3d, tree_index++, dir_flip);
680 BLI_kdtree_1d_insert(tree_1d, tree_index++, &
length);
686 BLI_kdtree_1d_insert(tree_1d, tree_index++, &
angle);
692 goto edge_select_all;
697 goto edge_select_all;
708 goto edge_select_all;
715 BLI_kdtree_1d_insert(tree_1d, tree_index++, value);
725 if (tree_1d !=
nullptr) {
726 BLI_kdtree_1d_deduplicate(tree_1d);
727 BLI_kdtree_1d_balance(tree_1d);
729 if (tree_3d !=
nullptr) {
730 BLI_kdtree_3d_deduplicate(tree_3d);
731 BLI_kdtree_3d_balance(tree_3d);
734 for (
Object *ob : objects) {
737 bool changed =
false;
739 bool has_custom_data_layer =
false;
752 if (!has_custom_data_layer) {
765 if (!has_custom_data_layer) {
777 float ob_m3[3][3], ob_m3_inv[3][3];
778 copy_m3_m4(ob_m3, ob->object_to_world().ptr());
781 int custom_data_offset;
808 const int delta_i = num_faces - num_faces_iter;
822 KDTreeNearest_3d nearest;
823 if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
863 if (!has_custom_data_layer) {
877 if (!has_custom_data_layer) {
904 params.calc_looptris =
false;
905 params.calc_normals =
false;
906 params.is_destructive =
false;
915 for (
Object *ob : objects) {
931 params.calc_looptris =
false;
932 params.calc_normals =
false;
933 params.is_destructive =
false;
938 BLI_kdtree_1d_free(tree_1d);
939 BLI_kdtree_3d_free(tree_3d);
940 if (gset !=
nullptr) {
961 const float thresh_radians = thresh *
float(
M_PI) + FLT_EPSILON;
964 int tot_verts_selected_all = 0;
968 for (
Object *ob : objects) {
973 if (tot_verts_selected_all == 0) {
978 KDTree_3d *tree_3d =
nullptr;
979 KDTree_1d *tree_1d =
nullptr;
985 tree_3d = BLI_kdtree_3d_new(tot_verts_selected_all);
988 tree_1d = BLI_kdtree_1d_new(tot_verts_selected_all);
996 int normal_tree_index = 0;
997 int tree_1d_index = 0;
998 for (
Object *ob : objects) {
1001 int cd_dvert_offset = -1;
1002 int cd_crease_offset = -1;
1004 int defbase_len = 0;
1006 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
1008 if (
bm->totvertsel == 0) {
1014 if (cd_dvert_offset == -1) {
1018 if (defbase_len == 0) {
1026 BLI_kdtree_1d_insert(tree_1d, tree_1d_index++, &
pos);
1050 BLI_kdtree_3d_insert(tree_3d, normal_tree_index++, normal);
1069 BLI_kdtree_1d_insert(tree_1d, tree_1d_index++, value);
1085 selected_vertex_groups.
add_as(dg->name);
1094 if (selected_vertex_groups.
is_empty()) {
1100 if (tree_1d !=
nullptr) {
1101 BLI_kdtree_1d_deduplicate(tree_1d);
1102 BLI_kdtree_1d_balance(tree_1d);
1104 if (tree_3d !=
nullptr) {
1105 BLI_kdtree_3d_deduplicate(tree_3d);
1106 BLI_kdtree_3d_balance(tree_3d);
1110 for (
Object *ob : objects) {
1113 bool changed =
false;
1114 bool has_crease_layer =
false;
1115 int cd_dvert_offset = -1;
1116 int cd_crease_offset = -1;
1118 int defbase_len = 0;
1122 if (cd_dvert_offset == -1) {
1127 if (defbase_len == 0) {
1135 bool found_any =
false;
1138 if (vgroup_id != -1) {
1143 if (found_any ==
false) {
1151 if (!has_crease_layer) {
1170 for (
const int num_edges_iter : connected_elems_num_set) {
1171 const int delta_i = num_edges - num_edges_iter;
1181 for (
const int num_faces_iter : connected_elems_num_set) {
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) {
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);
1323#ifdef WITH_FREESTYLE
1350 if (
STREQ(prop_id,
"compare")) {
1356 else if (
STREQ(prop_id,
"threshold")) {
1381 ot->name =
"Select Similar";
1382 ot->idname =
"MESH_OT_select_similar";
1383 ot->description =
"Select similar vertices, edges or faces by property types";
1401 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)
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)
bool EDBM_uvselect_clear(BMEditMesh *em)
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_ELEM_CD_GET_BOOL(ele, offset)
#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 *)