Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/mesh/editmesh_select_similar.c
| Show First 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
| #include "WM_api.h" | #include "WM_api.h" | ||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "RNA_access.h" | #include "RNA_access.h" | ||||
| #include "RNA_define.h" | #include "RNA_define.h" | ||||
| #include "ED_mesh.h" | #include "ED_mesh.h" | ||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "ED_select_utils.h" | |||||
| #include "mesh_intern.h" /* own include */ | #include "mesh_intern.h" /* own include */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Select Similar (Vert/Edge/Face) Operator - common | /** \name Select Similar (Vert/Edge/Face) Operator - common | ||||
| * \{ */ | * \{ */ | ||||
| enum { | |||||
| SIM_CMP_EQ = 0, | |||||
| SIM_CMP_GT, | |||||
| SIM_CMP_LT | |||||
| }; | |||||
| static const EnumPropertyItem prop_similar_compare_types[] = { | static const EnumPropertyItem prop_similar_compare_types[] = { | ||||
| {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""}, | {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""}, | ||||
| {SIM_CMP_GT, "GREATER", 0, "Greater", ""}, | {SIM_CMP_GT, "GREATER", 0, "Greater", ""}, | ||||
| {SIM_CMP_LT, "LESS", 0, "Less", ""}, | {SIM_CMP_LT, "LESS", 0, "Less", ""}, | ||||
| {0, NULL, 0, NULL, NULL} | {0, NULL, 0, NULL, NULL} | ||||
| }; | }; | ||||
| Show All 25 Lines | #endif | ||||
| {SIMFACE_FACEMAP, "FACE_MAP", 0, "Face-Map", ""}, | {SIMFACE_FACEMAP, "FACE_MAP", 0, "Face-Map", ""}, | ||||
| #ifdef WITH_FREESTYLE | #ifdef WITH_FREESTYLE | ||||
| {SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""}, | {SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""}, | ||||
| #endif | #endif | ||||
| {0, NULL, 0, NULL, NULL} | {0, NULL, 0, NULL, NULL} | ||||
| }; | }; | ||||
| static int mesh_select_similar_compare_float(const float delta, const float thresh, const int compare) | |||||
| { | |||||
| switch (compare) { | |||||
| case SIM_CMP_EQ: | |||||
| return (fabsf(delta) < thresh + FLT_EPSILON); | |||||
| case SIM_CMP_GT: | |||||
| return ((delta + thresh) > -FLT_EPSILON); | |||||
| case SIM_CMP_LT: | |||||
| return ((delta - thresh) < FLT_EPSILON); | |||||
| default: | |||||
| BLI_assert(0); | |||||
| return 0; | |||||
| } | |||||
| } | |||||
| static int mesh_select_similar_compare_int(const int delta, const int compare) | static int mesh_select_similar_compare_int(const int delta, const int compare) | ||||
| { | { | ||||
| switch (compare) { | switch (compare) { | ||||
| case SIM_CMP_EQ: | case SIM_CMP_EQ: | ||||
| return (delta == 0); | return (delta == 0); | ||||
| case SIM_CMP_GT: | case SIM_CMP_GT: | ||||
| return (delta > 0); | return (delta > 0); | ||||
| case SIM_CMP_LT: | case SIM_CMP_LT: | ||||
| return (delta < 0); | return (delta < 0); | ||||
| default: | default: | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| static bool mesh_select_similar_compare_float_tree(const KDTree *tree, const float length, const float thresh, const int compare) | |||||
| { | |||||
| /* Length of the edge we want to compare against. */ | |||||
| float nearest_edge_length; | |||||
| switch (compare) { | |||||
| case SIM_CMP_EQ: | |||||
| /* Compare to the edge closest to the current edge. */ | |||||
| nearest_edge_length = length; | |||||
| break; | |||||
| case SIM_CMP_GT: | |||||
| /* Compare against the shortest edge. */ | |||||
| /* -FLT_MAX leads to some precision issues and the wrong edge being selected. | |||||
| * For example, in a tree with 1, 2 and 3, which is stored squared as 1, 4, 9, it returns as the nearest | |||||
| * length/node the "4" instead of "1". */ | |||||
| nearest_edge_length = -1.0f; | |||||
| break; | |||||
| case SIM_CMP_LT: | |||||
| /* Compare against the longest edge. */ | |||||
| nearest_edge_length = FLT_MAX; | |||||
| break; | |||||
| default: | |||||
| BLI_assert(0); | |||||
| return false; | |||||
| } | |||||
| KDTreeNearest nearest; | |||||
| float dummy[3] = {nearest_edge_length, 0.0f, 0.0f}; | |||||
| if (BLI_kdtree_find_nearest(tree, dummy, &nearest) != -1) { | |||||
| float delta = length - nearest.co[0]; | |||||
| return mesh_select_similar_compare_float(delta, thresh, compare); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Select Similar Face | /** \name Select Similar Face | ||||
| * \{ */ | * \{ */ | ||||
| enum { | enum { | ||||
| SIMFACE_DATA_NONE = 0, | SIMFACE_DATA_NONE = 0, | ||||
| ▲ Show 20 Lines • Show All 310 Lines • ▼ Show 20 Lines | BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case SIMFACE_AREA: | case SIMFACE_AREA: | ||||
| { | { | ||||
| float area = BM_face_calc_area(face); | float area = BM_face_calc_area(face); | ||||
| if (mesh_select_similar_compare_float_tree(tree, area, thresh, compare)) { | if (ED_select_similar_compare_float_tree(tree, area, thresh, compare)) { | ||||
| select = true; | select = true; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case SIMFACE_PERIMETER: | case SIMFACE_PERIMETER: | ||||
| { | { | ||||
| float perimeter = BM_face_calc_perimeter(face); | float perimeter = BM_face_calc_perimeter(face); | ||||
| if (mesh_select_similar_compare_float_tree(tree, perimeter, thresh, compare)) { | if (ED_select_similar_compare_float_tree(tree, perimeter, thresh, compare)) { | ||||
| select = true; | select = true; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case SIMFACE_NORMAL: | case SIMFACE_NORMAL: | ||||
| { | { | ||||
| float normal[3]; | float normal[3]; | ||||
| copy_v3_v3(normal, face->no); | copy_v3_v3(normal, face->no); | ||||
| ▲ Show 20 Lines • Show All 382 Lines • ▼ Show 20 Lines | switch (type) { | ||||
| case SIMEDGE_CREASE: | case SIMEDGE_CREASE: | ||||
| case SIMEDGE_BEVEL: | case SIMEDGE_BEVEL: | ||||
| { | { | ||||
| has_custom_data_layer = CustomData_has_layer(&bm->edata, custom_data_type); | has_custom_data_layer = CustomData_has_layer(&bm->edata, custom_data_type); | ||||
| if (!has_custom_data_layer) { | if (!has_custom_data_layer) { | ||||
| /* Proceed only if we have to select all the edges that have custom data value of 0.0f. | /* Proceed only if we have to select all the edges that have custom data value of 0.0f. | ||||
| * In this case we will just select all the edges. | * In this case we will just select all the edges. | ||||
| * Otherwise continue the for loop. */ | * Otherwise continue the for loop. */ | ||||
| if (!mesh_select_similar_compare_float_tree(tree, 0.0f, thresh, compare)) { | if (!ED_select_similar_compare_float_tree(tree, 0.0f, thresh, compare)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BMEdge *edge; /* Mesh edge. */ | BMEdge *edge; /* Mesh edge. */ | ||||
| BMIter iter; /* Selected edges iterator. */ | BMIter iter; /* Selected edges iterator. */ | ||||
| Show All 31 Lines | BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) { | ||||
| select = true; | select = true; | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case SIMEDGE_LENGTH: | case SIMEDGE_LENGTH: | ||||
| { | { | ||||
| float length = edge_length_squared_worldspace_get(ob, edge); | float length = edge_length_squared_worldspace_get(ob, edge); | ||||
| if (mesh_select_similar_compare_float_tree(tree, length, thresh, compare)) { | if (ED_select_similar_compare_float_tree(tree, length, thresh, compare)) { | ||||
| select = true; | select = true; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case SIMEDGE_FACE_ANGLE: | case SIMEDGE_FACE_ANGLE: | ||||
| { | { | ||||
| if (BM_edge_face_count_at_most(edge, 2) == 2) { | if (BM_edge_face_count_at_most(edge, 2) == 2) { | ||||
| float angle = BM_edge_calc_face_angle(edge); | float angle = BM_edge_calc_face_angle(edge); | ||||
| if (mesh_select_similar_compare_float_tree(tree, angle, thresh, SIM_CMP_EQ)) { | if (ED_select_similar_compare_float_tree(tree, angle, thresh, SIM_CMP_EQ)) { | ||||
| select = true; | select = true; | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case SIMEDGE_SEAM: | case SIMEDGE_SEAM: | ||||
| if ((BM_elem_flag_test(edge, BM_ELEM_SEAM) != 0) == | if ((BM_elem_flag_test(edge, BM_ELEM_SEAM) != 0) == | ||||
| ((edge_data_value & SIMEDGE_DATA_TRUE) != 0)) | ((edge_data_value & SIMEDGE_DATA_TRUE) != 0)) | ||||
| Show All 30 Lines | BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) { | ||||
| case SIMEDGE_BEVEL: | case SIMEDGE_BEVEL: | ||||
| { | { | ||||
| if (!has_custom_data_layer) { | if (!has_custom_data_layer) { | ||||
| select = true; | select = true; | ||||
| break; | break; | ||||
| } | } | ||||
| const float *value = CustomData_bmesh_get(&bm->edata, edge->head.data, custom_data_type); | const float *value = CustomData_bmesh_get(&bm->edata, edge->head.data, custom_data_type); | ||||
| if (mesh_select_similar_compare_float_tree(tree, *value, thresh, compare)) { | if (ED_select_similar_compare_float_tree(tree, *value, thresh, compare)) { | ||||
| select = true; | select = true; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (select) { | if (select) { | ||||
| BM_edge_select_set(bm, edge, true); | BM_edge_select_set(bm, edge, true); | ||||
| ▲ Show 20 Lines • Show All 399 Lines • Show Last 20 Lines | |||||