Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Blackbourn <chrisbblend@gmail.com>2022-07-30 14:20:13 +0300
committerChris Blackbourn <chrisbblend@gmail.com>2022-07-30 14:24:11 +0300
commita5814607289a7e01d4844ee5ef724e6388cf044e (patch)
tree32db74c27e02e493c20fba2e6d97c15ea56a747e /source/blender/editors/uvedit/uvedit_select.c
parentd31886b3fe3b939fb86079d5fb607e80103078da (diff)
UV: Add options for uv select similar in island mode
In island selection mode, add new options for uv select similar: * Area UV * Area 3D * Face (number of faces in island) See also https://developer.blender.org/T47437 Differential Revision: https://developer.blender.org/D15553
Diffstat (limited to 'source/blender/editors/uvedit/uvedit_select.c')
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c169
1 files changed, 168 insertions, 1 deletions
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index d59dcb4f4ed..b1ed00e2c57 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -81,6 +81,7 @@ static void uv_select_tag_update_for_object(Depsgraph *depsgraph,
typedef enum {
UV_SSIM_AREA_UV = 1000,
UV_SSIM_AREA_3D,
+ UV_SSIM_FACE,
UV_SSIM_LENGTH_UV,
UV_SSIM_LENGTH_3D,
UV_SSIM_SIDES,
@@ -4638,6 +4639,33 @@ static float get_uv_face_needle(const eUVSelectSimilar type,
return result;
}
+static float get_uv_island_needle(const eUVSelectSimilar type,
+ const struct FaceIsland *island,
+ const float ob_m3[3][3],
+ const int cd_loop_uv_offset)
+
+{
+ float result = 0.0f;
+ switch (type) {
+ case UV_SSIM_AREA_UV:
+ for (int i = 0; i < island->faces_len; i++) {
+ result += BM_face_calc_area_uv(island->faces[i], cd_loop_uv_offset);
+ }
+ break;
+ case UV_SSIM_AREA_3D:
+ for (int i = 0; i < island->faces_len; i++) {
+ result += BM_face_calc_area_with_mat3(island->faces[i], ob_m3);
+ }
+ break;
+ case UV_SSIM_FACE:
+ return island->faces_len;
+ default:
+ BLI_assert_unreachable();
+ return false;
+ }
+ return result;
+}
+
static int uv_select_similar_vert_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -4969,6 +4997,136 @@ static int uv_select_similar_face_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static bool uv_island_selected(const Scene *scene, struct FaceIsland *island)
+{
+ BLI_assert(island && island->faces_len);
+ return uvedit_face_select_test(scene, island->faces[0], island->cd_loop_uv_offset);
+}
+
+static int uv_select_similar_island_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+
+ const eUVSelectSimilar type = RNA_enum_get(op->ptr, "type");
+ const float threshold = RNA_float_get(op->ptr, "threshold");
+ const eSimilarCmp compare = RNA_enum_get(op->ptr, "compare");
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+ view_layer, ((View3D *)NULL), &objects_len);
+
+ ListBase *island_list_ptr = MEM_callocN(sizeof(*island_list_ptr) * objects_len, __func__);
+ int island_list_len = 0;
+
+ const bool face_selected = !(scene->toolsettings->uv_flag & UV_SYNC_SELECTION);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ if (cd_loop_uv_offset == -1) {
+ continue;
+ }
+
+ float aspect_y = 1.0f; /* Placeholder value, aspect doesn't change connectivity. */
+ island_list_len += bm_mesh_calc_uv_islands(scene,
+ em->bm,
+ &island_list_ptr[ob_index],
+ face_selected,
+ false,
+ false,
+ aspect_y,
+ cd_loop_uv_offset);
+ }
+
+ struct FaceIsland **island_array = MEM_callocN(sizeof(*island_array) * island_list_len,
+ __func__);
+
+ int tree_index = 0;
+ KDTree_1d *tree_1d = BLI_kdtree_1d_new(island_list_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ if (cd_loop_uv_offset == -1) {
+ continue;
+ }
+
+ float ob_m3[3][3];
+ copy_m3_m4(ob_m3, obedit->obmat);
+
+ int index;
+ LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list_ptr[ob_index], index) {
+ island_array[index] = island;
+ if (!uv_island_selected(scene, island)) {
+ continue;
+ }
+ float needle = get_uv_island_needle(type, island, ob_m3, cd_loop_uv_offset);
+ if (tree_1d) {
+ BLI_kdtree_1d_insert(tree_1d, tree_index++, &needle);
+ }
+ }
+ }
+
+ if (tree_1d != NULL) {
+ BLI_kdtree_1d_deduplicate(tree_1d);
+ BLI_kdtree_1d_balance(tree_1d);
+ }
+
+ int tot_island_index = 0;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ if (cd_loop_uv_offset == -1) {
+ continue;
+ }
+ float ob_m3[3][3];
+ copy_m3_m4(ob_m3, obedit->obmat);
+
+ bool changed = false;
+ int index;
+ LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list_ptr[ob_index], index) {
+ island_array[tot_island_index++] = island; /* To deallocate later. */
+ if (uv_island_selected(scene, island)) {
+ continue;
+ }
+ float needle = get_uv_island_needle(type, island, ob_m3, cd_loop_uv_offset);
+ bool select = ED_select_similar_compare_float_tree(tree_1d, needle, threshold, compare);
+ if (!select) {
+ continue;
+ }
+ bool do_history = false;
+ for (int j = 0; j < island->faces_len; j++) {
+ uvedit_face_select_set(
+ scene, em, island->faces[j], select, do_history, island->cd_loop_uv_offset);
+ }
+ changed = true;
+ }
+
+ if (changed) {
+ uv_select_tag_update_for_object(depsgraph, ts, obedit);
+ }
+ }
+
+ BLI_assert(tot_island_index == island_list_len);
+ for (int i = 0; i < island_list_len; i++) {
+ MEM_SAFE_FREE(island_array[i]->faces);
+ MEM_SAFE_FREE(island_array[i]);
+ }
+
+ MEM_SAFE_FREE(island_array);
+ MEM_SAFE_FREE(island_list_ptr);
+ MEM_SAFE_FREE(objects);
+ BLI_kdtree_1d_free(tree_1d);
+
+ return OPERATOR_FINISHED;
+}
+
/* Select similar UV faces/edges/verts based on current selection. */
static int uv_select_similar_exec(bContext *C, wmOperator *op)
{
@@ -4990,7 +5148,7 @@ static int uv_select_similar_exec(bContext *C, wmOperator *op)
return uv_select_similar_face_exec(C, op);
}
if (selectmode & UV_SELECT_ISLAND) {
- // return uv_select_similar_island_exec(C, op);
+ return uv_select_similar_island_exec(C, op);
}
return uv_select_similar_vert_exec(C, op);
@@ -5011,6 +5169,12 @@ static EnumPropertyItem prop_face_similar_types[] = {
{UV_SSIM_MATERIAL, "MATERIAL", 0, "Material", ""},
{0}};
+static EnumPropertyItem prop_island_similar_types[] = {
+ {UV_SSIM_AREA_UV, "AREA", 0, "Area", ""},
+ {UV_SSIM_AREA_3D, "AREA_3D", 0, "Area 3D", ""},
+ {UV_SSIM_FACE, "FACE", 0, "Amount of Faces in Island", ""},
+ {0}};
+
static EnumPropertyItem prop_similar_compare_types[] = {{SIM_CMP_EQ, "EQUAL", 0, "Equal", ""},
{SIM_CMP_GT, "GREATER", 0, "Greater", ""},
{SIM_CMP_LT, "LESS", 0, "Less", ""},
@@ -5030,6 +5194,9 @@ static const EnumPropertyItem *uv_select_similar_type_itemf(bContext *C,
if (selectmode & UV_SELECT_FACE) {
return prop_face_similar_types;
}
+ if (selectmode & UV_SELECT_ISLAND) {
+ return prop_island_similar_types;
+ }
}
return prop_vert_similar_types;