Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/uvedit/uvedit_rip.c
| Show First 20 Lines • Show All 180 Lines • ▼ Show 20 Lines | static BMLoop *bm_vert_step_fan_loop_uv(BMLoop *l, BMEdge **e_step, const int cd_loop_uv_offset) | ||||
| *e_step = l_next->e; | *e_step = l_next->e; | ||||
| return bm_loop_find_other_fan_loop_with_visible_face(l_next, l->v, cd_loop_uv_offset); | return bm_loop_find_other_fan_loop_with_visible_face(l_next, l->v, cd_loop_uv_offset); | ||||
| } | } | ||||
| static void bm_loop_uv_select_single_vert_validate(BMLoop *l_init, const int cd_loop_uv_offset) | static void bm_loop_uv_select_single_vert_validate(BMLoop *l_init, const int cd_loop_uv_offset) | ||||
| { | { | ||||
| const MLoopUV *luv_init = BM_ELEM_CD_GET_VOID_P(l_init, cd_loop_uv_offset); | const float *luv_init = BM_ELEM_CD_GET_FLOAT_P(l_init, cd_loop_uv_offset); | ||||
| BMIter liter; | BMIter liter; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| bool is_single_vert = true; | bool is_single_vert = true; | ||||
| BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) { | BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) { | ||||
| const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); | ||||
| if (equals_v2v2(luv_init->uv, luv->uv)) { | if (equals_v2v2(luv_init, luv)) { | ||||
| if (UL(l->prev)->is_select_edge || UL(l)->is_select_edge) { | if (UL(l->prev)->is_select_edge || UL(l)->is_select_edge) { | ||||
| is_single_vert = false; | is_single_vert = false; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (is_single_vert == false) { | if (is_single_vert == false) { | ||||
| BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) { | BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) { | ||||
| if (UL(l)->is_select_vert_single) { | if (UL(l)->is_select_vert_single) { | ||||
| const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); | ||||
| if (equals_v2v2(luv_init->uv, luv->uv)) { | if (equals_v2v2(luv_init, luv)) { | ||||
| UL(l)->is_select_vert_single = false; | UL(l)->is_select_vert_single = false; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * The corner return values calculate the angle between both loops, | * The corner return values calculate the angle between both loops, | ||||
| * the edge values pick the closest to the either edge (ignoring the center). | * the edge values pick the closest to the either edge (ignoring the center). | ||||
| * | * | ||||
| * \param dir: Direction to calculate the angle to (normalized and aspect corrected). | * \param dir: Direction to calculate the angle to (normalized and aspect corrected). | ||||
| */ | */ | ||||
| static void bm_loop_calc_uv_angle_from_dir(BMLoop *l, | static void bm_loop_calc_uv_angle_from_dir(BMLoop *l, | ||||
| const float dir[2], | const float dir[2], | ||||
| const float aspect_y, | const float aspect_y, | ||||
| const int cd_loop_uv_offset, | const int cd_loop_uv_offset, | ||||
| float *r_corner_angle, | float *r_corner_angle, | ||||
| float *r_edge_angle, | float *r_edge_angle, | ||||
| int *r_edge_index) | int *r_edge_index) | ||||
| { | { | ||||
| /* Calculate 3 directions, return the shortest angle. */ | /* Calculate 3 directions, return the shortest angle. */ | ||||
| float dir_test[3][2]; | float dir_test[3][2]; | ||||
| const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); | ||||
| const MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset); | const float *luv_prev = BM_ELEM_CD_GET_FLOAT_P(l->prev, cd_loop_uv_offset); | ||||
| const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); | const float *luv_next = BM_ELEM_CD_GET_FLOAT_P(l->next, cd_loop_uv_offset); | ||||
| sub_v2_v2v2(dir_test[0], luv->uv, luv_prev->uv); | sub_v2_v2v2(dir_test[0], luv, luv_prev); | ||||
| sub_v2_v2v2(dir_test[2], luv->uv, luv_next->uv); | sub_v2_v2v2(dir_test[2], luv, luv_next); | ||||
| dir_test[0][1] /= aspect_y; | dir_test[0][1] /= aspect_y; | ||||
| dir_test[2][1] /= aspect_y; | dir_test[2][1] /= aspect_y; | ||||
| normalize_v2(dir_test[0]); | normalize_v2(dir_test[0]); | ||||
| normalize_v2(dir_test[2]); | normalize_v2(dir_test[2]); | ||||
| /* Calculate the orthogonal line (same as negating one, then adding). */ | /* Calculate the orthogonal line (same as negating one, then adding). */ | ||||
| sub_v2_v2v2(dir_test[1], dir_test[0], dir_test[2]); | sub_v2_v2v2(dir_test[1], dir_test[0], dir_test[2]); | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
| * \note This matches the behavior of edit-mesh rip tool. | * \note This matches the behavior of edit-mesh rip tool. | ||||
| */ | */ | ||||
| static UVRipSingle *uv_rip_single_from_loop(BMLoop *l_init_orig, | static UVRipSingle *uv_rip_single_from_loop(BMLoop *l_init_orig, | ||||
| const float co[2], | const float co[2], | ||||
| const float aspect_y, | const float aspect_y, | ||||
| const int cd_loop_uv_offset) | const int cd_loop_uv_offset) | ||||
| { | { | ||||
| UVRipSingle *rip = MEM_callocN(sizeof(*rip), __func__); | UVRipSingle *rip = MEM_callocN(sizeof(*rip), __func__); | ||||
| const float *co_center = | const float *co_center = BM_ELEM_CD_GET_FLOAT_P(l_init_orig, cd_loop_uv_offset); | ||||
| (((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_init_orig, cd_loop_uv_offset))->uv); | |||||
| rip->loops = BLI_gset_ptr_new(__func__); | rip->loops = BLI_gset_ptr_new(__func__); | ||||
| /* Track the closest loop, start walking from this so in the event we have multiple | /* Track the closest loop, start walking from this so in the event we have multiple | ||||
| * disconnected fans, we can rip away loops connected to this one. */ | * disconnected fans, we can rip away loops connected to this one. */ | ||||
| BMLoop *l_init = NULL; | BMLoop *l_init = NULL; | ||||
| BMLoop *l_init_edge = NULL; | BMLoop *l_init_edge = NULL; | ||||
| float corner_angle_best = FLT_MAX; | float corner_angle_best = FLT_MAX; | ||||
| float edge_angle_best = FLT_MAX; | float edge_angle_best = FLT_MAX; | ||||
| int edge_index_best = 0; /* -1 or +1 (never center). */ | int edge_index_best = 0; /* -1 or +1 (never center). */ | ||||
| /* Calculate the direction from the cursor with aspect correction. */ | /* Calculate the direction from the cursor with aspect correction. */ | ||||
| float dir_co[2]; | float dir_co[2]; | ||||
| sub_v2_v2v2(dir_co, co_center, co); | sub_v2_v2v2(dir_co, co_center, co); | ||||
| dir_co[1] /= aspect_y; | dir_co[1] /= aspect_y; | ||||
| if (UNLIKELY(normalize_v2(dir_co) == 0.0)) { | if (UNLIKELY(normalize_v2(dir_co) == 0.0)) { | ||||
| dir_co[1] = 1.0f; | dir_co[1] = 1.0f; | ||||
| } | } | ||||
| int uv_fan_count_all = 0; | int uv_fan_count_all = 0; | ||||
| { | { | ||||
| BMIter liter; | BMIter liter; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BM_ITER_ELEM (l, &liter, l_init_orig->v, BM_LOOPS_OF_VERT) { | BM_ITER_ELEM (l, &liter, l_init_orig->v, BM_LOOPS_OF_VERT) { | ||||
| if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) { | if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) { | ||||
| const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); | ||||
| if (equals_v2v2(co_center, luv->uv)) { | if (equals_v2v2(co_center, luv)) { | ||||
| uv_fan_count_all += 1; | uv_fan_count_all += 1; | ||||
| /* Clear at the same time. */ | /* Clear at the same time. */ | ||||
| UL(l)->is_select_vert_single = true; | UL(l)->is_select_vert_single = true; | ||||
| UL(l)->side = 0; | UL(l)->side = 0; | ||||
| BLI_gset_add(rip->loops, l); | BLI_gset_add(rip->loops, l); | ||||
| /* Update `l_init_close` */ | /* Update `l_init_close` */ | ||||
| float corner_angle_test; | float corner_angle_test; | ||||
| ▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | |||||
| * this is only needed for rip-pairs end-points (only two per contiguous selection loop). | * this is only needed for rip-pairs end-points (only two per contiguous selection loop). | ||||
| */ | */ | ||||
| static float uv_rip_pairs_calc_uv_angle(BMLoop *l_init, | static float uv_rip_pairs_calc_uv_angle(BMLoop *l_init, | ||||
| uint side, | uint side, | ||||
| const float aspect_y, | const float aspect_y, | ||||
| const int cd_loop_uv_offset) | const int cd_loop_uv_offset) | ||||
| { | { | ||||
| BMIter liter; | BMIter liter; | ||||
| const MLoopUV *luv_init = BM_ELEM_CD_GET_VOID_P(l_init, cd_loop_uv_offset); | const float *luv_init = BM_ELEM_CD_GET_FLOAT_P(l_init, cd_loop_uv_offset); | ||||
| float angle_of_side = 0.0f; | float angle_of_side = 0.0f; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) { | BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) { | ||||
| if (UL(l)->in_rip_pairs) { | if (UL(l)->in_rip_pairs) { | ||||
| if (UL(l)->side == side) { | if (UL(l)->side == side) { | ||||
| const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); | ||||
| if (equals_v2v2(luv_init->uv, luv->uv)) { | if (equals_v2v2(luv_init, luv)) { | ||||
| const MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset); | const float *luv_prev = BM_ELEM_CD_GET_FLOAT_P(l->prev, cd_loop_uv_offset); | ||||
| const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); | const float *luv_next = BM_ELEM_CD_GET_FLOAT_P(l->next, cd_loop_uv_offset); | ||||
| float dir_prev[2], dir_next[2]; | float dir_prev[2], dir_next[2]; | ||||
| sub_v2_v2v2(dir_prev, luv_prev->uv, luv->uv); | sub_v2_v2v2(dir_prev, luv_prev, luv); | ||||
| sub_v2_v2v2(dir_next, luv_next->uv, luv->uv); | sub_v2_v2v2(dir_next, luv_next, luv); | ||||
| dir_prev[1] /= aspect_y; | dir_prev[1] /= aspect_y; | ||||
| dir_next[1] /= aspect_y; | dir_next[1] /= aspect_y; | ||||
| const float luv_angle = angle_v2v2(dir_prev, dir_next); | const float luv_angle = angle_v2v2(dir_prev, dir_next); | ||||
| if (LIKELY(isfinite(luv_angle))) { | if (LIKELY(isfinite(luv_angle))) { | ||||
| angle_of_side += luv_angle; | angle_of_side += luv_angle; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return angle_of_side; | return angle_of_side; | ||||
| } | } | ||||
| static int uv_rip_pairs_loop_count_on_side(BMLoop *l_init, uint side, const int cd_loop_uv_offset) | static int uv_rip_pairs_loop_count_on_side(BMLoop *l_init, uint side, const int cd_loop_uv_offset) | ||||
| { | { | ||||
| const MLoopUV *luv_init = BM_ELEM_CD_GET_VOID_P(l_init, cd_loop_uv_offset); | const float *luv_init = BM_ELEM_CD_GET_FLOAT_P(l_init, cd_loop_uv_offset); | ||||
| int count = 0; | int count = 0; | ||||
| BMIter liter; | BMIter liter; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) { | BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) { | ||||
| if (UL(l)->in_rip_pairs) { | if (UL(l)->in_rip_pairs) { | ||||
| if (UL(l)->side == side) { | if (UL(l)->side == side) { | ||||
| const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); | ||||
| if (equals_v2v2(luv_init->uv, luv->uv)) { | if (equals_v2v2(luv_init, luv)) { | ||||
| count += 1; | count += 1; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return count; | return count; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 179 Lines • ▼ Show 20 Lines | static bool uv_rip_pairs_calc_center_and_direction(UVRipPairs *rip, | ||||
| for (int i = 0; i < 2; i++) { | for (int i = 0; i < 2; i++) { | ||||
| zero_v2(r_dir_side[i]); | zero_v2(r_dir_side[i]); | ||||
| } | } | ||||
| GSetIterator gs_iter; | GSetIterator gs_iter; | ||||
| GSET_ITER (gs_iter, rip->loops) { | GSET_ITER (gs_iter, rip->loops) { | ||||
| BMLoop *l = BLI_gsetIterator_getKey(&gs_iter); | BMLoop *l = BLI_gsetIterator_getKey(&gs_iter); | ||||
| int side = UL(l)->side; | int side = UL(l)->side; | ||||
| const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); | ||||
| add_v2_v2(r_center, luv->uv); | add_v2_v2(r_center, luv); | ||||
| float dir[2]; | float dir[2]; | ||||
| if (!UL(l)->is_select_edge) { | if (!UL(l)->is_select_edge) { | ||||
| const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); | const float *luv_next = BM_ELEM_CD_GET_FLOAT_P(l->next, cd_loop_uv_offset); | ||||
| sub_v2_v2v2(dir, luv_next->uv, luv->uv); | sub_v2_v2v2(dir, luv_next, luv); | ||||
| add_v2_v2(r_dir_side[side], dir); | add_v2_v2(r_dir_side[side], dir); | ||||
| } | } | ||||
| if (!UL(l->prev)->is_select_edge) { | if (!UL(l->prev)->is_select_edge) { | ||||
| const MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset); | const float *luv_prev = BM_ELEM_CD_GET_FLOAT_P(l->prev, cd_loop_uv_offset); | ||||
| sub_v2_v2v2(dir, luv_prev->uv, luv->uv); | sub_v2_v2v2(dir, luv_prev, luv); | ||||
| add_v2_v2(r_dir_side[side], dir); | add_v2_v2(r_dir_side[side], dir); | ||||
| } | } | ||||
| side_total[side] += 1; | side_total[side] += 1; | ||||
| } | } | ||||
| center_total += BLI_gset_len(rip->loops); | center_total += BLI_gset_len(rip->loops); | ||||
| for (int i = 0; i < 2; i++) { | for (int i = 0; i < 2; i++) { | ||||
| normalize_v2(r_dir_side[i]); | normalize_v2(r_dir_side[i]); | ||||
| Show All 13 Lines | |||||
| /** | /** | ||||
| * \return true when a change was made. | * \return true when a change was made. | ||||
| */ | */ | ||||
| static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const float aspect_y) | static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const float aspect_y) | ||||
| { | { | ||||
| Mesh *me = (Mesh *)obedit->data; | Mesh *me = (Mesh *)obedit->data; | ||||
| BMEditMesh *em = me->edit_mesh; | BMEditMesh *em = me->edit_mesh; | ||||
| BMesh *bm = em->bm; | BMesh *bm = em->bm; | ||||
| const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); | const char *active_uv_name = CustomData_get_active_layer_name(&bm->ldata, CD_PROP_FLOAT2); | ||||
| BM_uv_map_ensure_vert_select_attr(bm, active_uv_name); | |||||
| BM_uv_map_ensure_edge_select_attr(bm, active_uv_name); | |||||
| const BMUVOffsets offsets = BM_uv_map_get_offsets(bm); | |||||
| BMFace *efa; | BMFace *efa; | ||||
| BMIter iter, liter; | BMIter iter, liter; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| const ULData ul_clear = {0}; | const ULData ul_clear = {0}; | ||||
| bool changed = false; | bool changed = false; | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| BM_elem_flag_set(efa, BM_ELEM_TAG, uvedit_face_visible_test(scene, efa)); | BM_elem_flag_set(efa, BM_ELEM_TAG, uvedit_face_visible_test(scene, efa)); | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| ULData *ul = UL(l); | ULData *ul = UL(l); | ||||
| *ul = ul_clear; | *ul = ul_clear; | ||||
| } | } | ||||
| } | } | ||||
| bm->elem_index_dirty |= BM_LOOP; | bm->elem_index_dirty |= BM_LOOP; | ||||
| bool is_select_all_any = false; | bool is_select_all_any = false; | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { | if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { | ||||
| bool is_all = true; | bool is_all = true; | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | if (BM_ELEM_CD_GET_BOOL(l, offsets.select_vert)) { | ||||
| if (luv->flag & MLOOPUV_VERTSEL) { | if (BM_ELEM_CD_GET_BOOL(l, offsets.select_edge)) { | ||||
| const MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset); | |||||
| if (luv->flag & MLOOPUV_EDGESEL) { | |||||
| UL(l)->is_select_edge = true; | UL(l)->is_select_edge = true; | ||||
| } | } | ||||
| else if ((luv_prev->flag & MLOOPUV_EDGESEL) == 0) { | else if (!BM_ELEM_CD_GET_BOOL(l->prev, offsets.select_edge)) { | ||||
| /* #bm_loop_uv_select_single_vert_validate validates below. */ | /* #bm_loop_uv_select_single_vert_validate validates below. */ | ||||
| UL(l)->is_select_vert_single = true; | UL(l)->is_select_vert_single = true; | ||||
| is_all = false; | is_all = false; | ||||
| } | } | ||||
| else { | else { | ||||
| /* Cases where all vertices of a face are selected but not all edges are selected. */ | /* Cases where all vertices of a face are selected but not all edges are selected. */ | ||||
| is_all = false; | is_all = false; | ||||
| } | } | ||||
| Show All 11 Lines | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| } | } | ||||
| } | } | ||||
| /* Remove #ULData.is_select_vert_single when connected to selected edges. */ | /* Remove #ULData.is_select_vert_single when connected to selected edges. */ | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { | if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| if (UL(l)->is_select_vert_single) { | if (UL(l)->is_select_vert_single) { | ||||
| bm_loop_uv_select_single_vert_validate(l, cd_loop_uv_offset); | bm_loop_uv_select_single_vert_validate(l, offsets.uv); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Special case: if we have selected faces, isolate them. | /* Special case: if we have selected faces, isolate them. | ||||
| * This isn't a rip, however it's useful for users as a quick way | * This isn't a rip, however it's useful for users as a quick way | ||||
| * to detach the selection. | * to detach the selection. | ||||
| * | * | ||||
| * We could also extract an edge loop from the boundary | * We could also extract an edge loop from the boundary | ||||
| * however in practice it's not that useful, see T78751. */ | * however in practice it's not that useful, see T78751. */ | ||||
| if (is_select_all_any) { | if (is_select_all_any) { | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| if (!UL(l)->is_select_all) { | if (!UL(l)->is_select_all) { | ||||
| MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | if (BM_ELEM_CD_GET_BOOL(l, offsets.select_vert)) { | ||||
| if (luv->flag & MLOOPUV_VERTSEL) { | BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, false); | ||||
| luv->flag &= ~MLOOPUV_VERTSEL; | |||||
| changed = true; | changed = true; | ||||
| } | } | ||||
| if (luv->flag & MLOOPUV_EDGESEL) { | if (BM_ELEM_CD_GET_BOOL(l, offsets.select_edge)) { | ||||
| luv->flag &= ~MLOOPUV_EDGESEL; | BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, false); | ||||
| changed = true; | changed = true; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return changed; | return changed; | ||||
| } | } | ||||
| /* Extract loop pairs or single loops. */ | /* Extract loop pairs or single loops. */ | ||||
| BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | ||||
| if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { | if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| if (UL(l)->is_select_edge) { | if (UL(l)->is_select_edge) { | ||||
| if (!UL(l)->in_rip_pairs) { | if (!UL(l)->in_rip_pairs) { | ||||
| UVRipPairs *rip = uv_rip_pairs_from_loop(l, aspect_y, cd_loop_uv_offset); | UVRipPairs *rip = uv_rip_pairs_from_loop(l, aspect_y, offsets.uv); | ||||
| float center[2]; | float center[2]; | ||||
| float dir_cursor[2]; | float dir_cursor[2]; | ||||
| float dir_side[2][2]; | float dir_side[2][2]; | ||||
| int side_from_cursor = -1; | int side_from_cursor = -1; | ||||
| if (uv_rip_pairs_calc_center_and_direction(rip, cd_loop_uv_offset, center, dir_side)) { | if (uv_rip_pairs_calc_center_and_direction(rip, offsets.uv, center, dir_side)) { | ||||
| for (int i = 0; i < 2; i++) { | for (int i = 0; i < 2; i++) { | ||||
| sub_v2_v2v2(dir_cursor, center, co); | sub_v2_v2v2(dir_cursor, center, co); | ||||
| normalize_v2(dir_cursor); | normalize_v2(dir_cursor); | ||||
| } | } | ||||
| side_from_cursor = (dot_v2v2(dir_side[0], dir_cursor) - | side_from_cursor = (dot_v2v2(dir_side[0], dir_cursor) - | ||||
| dot_v2v2(dir_side[1], dir_cursor)) < 0.0f; | dot_v2v2(dir_side[1], dir_cursor)) < 0.0f; | ||||
| } | } | ||||
| GSetIterator gs_iter; | GSetIterator gs_iter; | ||||
| GSET_ITER (gs_iter, rip->loops) { | GSET_ITER (gs_iter, rip->loops) { | ||||
| BMLoop *l_iter = BLI_gsetIterator_getKey(&gs_iter); | BMLoop *l_iter = BLI_gsetIterator_getKey(&gs_iter); | ||||
| ULData *ul = UL(l_iter); | ULData *ul = UL(l_iter); | ||||
| if (ul->side == side_from_cursor) { | if (ul->side == side_from_cursor) { | ||||
| uvedit_uv_select_disable(scene, em->bm, l_iter, cd_loop_uv_offset); | uvedit_uv_select_disable(scene, bm, l_iter, offsets); | ||||
| changed = true; | changed = true; | ||||
| } | } | ||||
| /* Ensure we don't operate on these again. */ | /* Ensure we don't operate on these again. */ | ||||
| *ul = ul_clear; | *ul = ul_clear; | ||||
| } | } | ||||
| uv_rip_pairs_free(rip); | uv_rip_pairs_free(rip); | ||||
| } | } | ||||
| } | } | ||||
| else if (UL(l)->is_select_vert_single) { | else if (UL(l)->is_select_vert_single) { | ||||
| UVRipSingle *rip = uv_rip_single_from_loop(l, co, aspect_y, cd_loop_uv_offset); | UVRipSingle *rip = uv_rip_single_from_loop(l, co, aspect_y, offsets.uv); | ||||
| /* We only ever use one side. */ | /* We only ever use one side. */ | ||||
| const int side_from_cursor = 0; | const int side_from_cursor = 0; | ||||
| GSetIterator gs_iter; | GSetIterator gs_iter; | ||||
| GSET_ITER (gs_iter, rip->loops) { | GSET_ITER (gs_iter, rip->loops) { | ||||
| BMLoop *l_iter = BLI_gsetIterator_getKey(&gs_iter); | BMLoop *l_iter = BLI_gsetIterator_getKey(&gs_iter); | ||||
| ULData *ul = UL(l_iter); | ULData *ul = UL(l_iter); | ||||
| if (ul->side == side_from_cursor) { | if (ul->side == side_from_cursor) { | ||||
| uvedit_uv_select_disable(scene, em->bm, l_iter, cd_loop_uv_offset); | uvedit_uv_select_disable(scene, bm, l_iter, offsets); | ||||
| changed = true; | changed = true; | ||||
| } | } | ||||
| /* Ensure we don't operate on these again. */ | /* Ensure we don't operate on these again. */ | ||||
| *ul = ul_clear; | *ul = ul_clear; | ||||
| } | } | ||||
| uv_rip_single_free(rip); | uv_rip_single_free(rip); | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 98 Lines • Show Last 20 Lines | |||||