Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/mesh/editmesh_utils.c
| Show First 20 Lines • Show All 453 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| BMVert *ev; | BMVert *ev; | ||||
| BMFace *efa; | BMFace *efa; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BMIter iter, liter; | BMIter iter, liter; | ||||
| /* vars from original func */ | /* vars from original func */ | ||||
| UvVertMap *vmap; | UvVertMap *vmap; | ||||
| UvMapVert *buf; | UvMapVert *buf; | ||||
| const MLoopUV *luv; | const float(*luv)[2]; | ||||
| uint a; | uint a; | ||||
| int totverts, i, totuv, totfaces; | int totverts, i, totuv, totfaces; | ||||
| const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2); | ||||
| bool *winding = NULL; | bool *winding = NULL; | ||||
| BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); | BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); | ||||
| BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); | BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); | ||||
| totfaces = bm->totface; | totfaces = bm->totface; | ||||
| totverts = bm->totvert; | totverts = bm->totvert; | ||||
| totuv = 0; | totuv = 0; | ||||
| Show All 37 Lines | if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| buf->poly_index = a; | buf->poly_index = a; | ||||
| buf->separate = 0; | buf->separate = 0; | ||||
| buf->next = vmap->vert[BM_elem_index_get(l->v)]; | buf->next = vmap->vert[BM_elem_index_get(l->v)]; | ||||
| vmap->vert[BM_elem_index_get(l->v)] = buf; | vmap->vert[BM_elem_index_get(l->v)] = buf; | ||||
| buf++; | buf++; | ||||
| if (use_winding) { | if (use_winding) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | luv = BM_ELEM_CD_GET_FLOAT2_P(l, cd_loop_uv_offset); | ||||
| copy_v2_v2(tf_uv[i], luv->uv); | copy_v2_v2(tf_uv[i], *luv); | ||||
| } | } | ||||
| } | } | ||||
| if (use_winding) { | if (use_winding) { | ||||
| winding[a] = cross_poly_v2(tf_uv, efa->len) > 0; | winding[a] = cross_poly_v2(tf_uv, efa->len) > 0; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* sort individual uvs for each vert */ | /* sort individual uvs for each vert */ | ||||
| BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, a) { | BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, a) { | ||||
| UvMapVert *newvlist = NULL, *vlist = vmap->vert[a]; | UvMapVert *newvlist = NULL, *vlist = vmap->vert[a]; | ||||
| UvMapVert *iterv, *v, *lastv, *next; | UvMapVert *iterv, *v, *lastv, *next; | ||||
| const float *uv, *uv2; | const float *uv, *uv2; | ||||
| while (vlist) { | while (vlist) { | ||||
| v = vlist; | v = vlist; | ||||
| vlist = vlist->next; | vlist = vlist->next; | ||||
| v->next = newvlist; | v->next = newvlist; | ||||
| newvlist = v; | newvlist = v; | ||||
| efa = BM_face_at_index(bm, v->poly_index); | efa = BM_face_at_index(bm, v->poly_index); | ||||
| l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->loop_of_poly_index); | l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->loop_of_poly_index); | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | uv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); | ||||
| uv = luv->uv; | |||||
| lastv = NULL; | lastv = NULL; | ||||
| iterv = vlist; | iterv = vlist; | ||||
| while (iterv) { | while (iterv) { | ||||
| next = iterv->next; | next = iterv->next; | ||||
| efa = BM_face_at_index(bm, iterv->poly_index); | efa = BM_face_at_index(bm, iterv->poly_index); | ||||
| l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->loop_of_poly_index); | l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->loop_of_poly_index); | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | uv2 = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); | ||||
| uv2 = luv->uv; | |||||
| if (compare_v2v2(uv2, uv, STD_UV_CONNECT_LIMIT) && | if (compare_v2v2(uv2, uv, STD_UV_CONNECT_LIMIT) && | ||||
| (!use_winding || winding[iterv->poly_index] == winding[v->poly_index])) { | (!use_winding || winding[iterv->poly_index] == winding[v->poly_index])) { | ||||
| if (lastv) { | if (lastv) { | ||||
| lastv->next = next; | lastv->next = next; | ||||
| } | } | ||||
| else { | else { | ||||
| vlist = next; | vlist = next; | ||||
| ▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | static void bm_uv_assign_island(UvElementMap *element_map, | ||||
| islandbuf[islandbufsize].flag = element->flag; | islandbuf[islandbufsize].flag = element->flag; | ||||
| } | } | ||||
| static int bm_uv_edge_select_build_islands(UvElementMap *element_map, | static int bm_uv_edge_select_build_islands(UvElementMap *element_map, | ||||
| const Scene *scene, | const Scene *scene, | ||||
| UvElement *islandbuf, | UvElement *islandbuf, | ||||
| uint *map, | uint *map, | ||||
| bool uv_selected, | bool uv_selected, | ||||
| const int cd_loop_uv_offset) | const BMUVOffsets offsets) | ||||
| { | { | ||||
| BM_uv_element_map_ensure_head_table(element_map); | BM_uv_element_map_ensure_head_table(element_map); | ||||
| int total_uvs = element_map->total_uvs; | int total_uvs = element_map->total_uvs; | ||||
| /* Depth first search the graph, building islands as we go. */ | /* Depth first search the graph, building islands as we go. */ | ||||
| int nislands = 0; | int nislands = 0; | ||||
| int islandbufsize = 0; | int islandbufsize = 0; | ||||
| Show All 24 Lines | for (int i = 0; i < total_uvs; i++) { | ||||
| /* Traverse the graph. */ | /* Traverse the graph. */ | ||||
| while (stacksize_uv) { | while (stacksize_uv) { | ||||
| BLI_assert(stacksize_uv < stack_upper_bound); | BLI_assert(stacksize_uv < stack_upper_bound); | ||||
| element = stack_uv[--stacksize_uv]; | element = stack_uv[--stacksize_uv]; | ||||
| while (element) { | while (element) { | ||||
| /* Scan forwards around the BMFace that contains element->l. */ | /* Scan forwards around the BMFace that contains element->l. */ | ||||
| if (!uv_selected || uvedit_edge_select_test(scene, element->l, cd_loop_uv_offset)) { | if (!uv_selected || uvedit_edge_select_test(scene, element->l, offsets)) { | ||||
| UvElement *next = BM_uv_element_get(element_map, element->l->next->f, element->l->next); | UvElement *next = BM_uv_element_get(element_map, element->l->next->f, element->l->next); | ||||
| if (next->island == INVALID_ISLAND) { | if (next->island == INVALID_ISLAND) { | ||||
| UvElement *tail = element_map->head_table[next - element_map->storage]; | UvElement *tail = element_map->head_table[next - element_map->storage]; | ||||
| stack_uv[stacksize_uv++] = tail; | stack_uv[stacksize_uv++] = tail; | ||||
| while (tail) { | while (tail) { | ||||
| bm_uv_assign_island(element_map, tail, nislands, map, islandbuf, islandbufsize++); | bm_uv_assign_island(element_map, tail, nislands, map, islandbuf, islandbufsize++); | ||||
| tail = tail->next; | tail = tail->next; | ||||
| if (tail && tail->separate) { | if (tail && tail->separate) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Scan backwards around the BMFace that contains element->l. */ | /* Scan backwards around the BMFace that contains element->l. */ | ||||
| if (!uv_selected || uvedit_edge_select_test(scene, element->l->prev, cd_loop_uv_offset)) { | if (!uv_selected || uvedit_edge_select_test(scene, element->l->prev, offsets)) { | ||||
| UvElement *prev = BM_uv_element_get(element_map, element->l->prev->f, element->l->prev); | UvElement *prev = BM_uv_element_get(element_map, element->l->prev->f, element->l->prev); | ||||
| if (prev->island == INVALID_ISLAND) { | if (prev->island == INVALID_ISLAND) { | ||||
| UvElement *tail = element_map->head_table[prev - element_map->storage]; | UvElement *tail = element_map->head_table[prev - element_map->storage]; | ||||
| stack_uv[stacksize_uv++] = tail; | stack_uv[stacksize_uv++] = tail; | ||||
| while (tail) { | while (tail) { | ||||
| bm_uv_assign_island(element_map, tail, nislands, map, islandbuf, islandbufsize++); | bm_uv_assign_island(element_map, tail, nislands, map, islandbuf, islandbufsize++); | ||||
| tail = tail->next; | tail = tail->next; | ||||
| if (tail && tail->separate) { | if (tail && tail->separate) { | ||||
| Show All 32 Lines | static void bm_uv_build_islands(UvElementMap *element_map, | ||||
| /* map holds the map from current vmap->buf to the new, sorted map */ | /* map holds the map from current vmap->buf to the new, sorted map */ | ||||
| uint *map = MEM_mallocN(sizeof(*map) * totuv, "uvelement_remap"); | uint *map = MEM_mallocN(sizeof(*map) * totuv, "uvelement_remap"); | ||||
| BMFace **stack = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_face_stack"); | BMFace **stack = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_face_stack"); | ||||
| UvElement *islandbuf = MEM_callocN(sizeof(*islandbuf) * totuv, "uvelement_island_buffer"); | UvElement *islandbuf = MEM_callocN(sizeof(*islandbuf) * totuv, "uvelement_island_buffer"); | ||||
| /* Island number for BMFaces. */ | /* Island number for BMFaces. */ | ||||
| int *island_number = MEM_callocN(sizeof(*island_number) * bm->totface, "uv_island_number_face"); | int *island_number = MEM_callocN(sizeof(*island_number) * bm->totface, "uv_island_number_face"); | ||||
| copy_vn_i(island_number, bm->totface, INVALID_ISLAND); | copy_vn_i(island_number, bm->totface, INVALID_ISLAND); | ||||
| const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | const BMUVOffsets uv_offsets = BM_uv_map_get_offsets(bm); | ||||
| const bool use_uv_edge_connectivity = scene->toolsettings->uv_flag & UV_SYNC_SELECTION ? | const bool use_uv_edge_connectivity = scene->toolsettings->uv_flag & UV_SYNC_SELECTION ? | ||||
| scene->toolsettings->selectmode & SCE_SELECT_EDGE : | scene->toolsettings->selectmode & SCE_SELECT_EDGE : | ||||
| scene->toolsettings->uv_selectmode & UV_SELECT_EDGE; | scene->toolsettings->uv_selectmode & UV_SELECT_EDGE; | ||||
| if (use_uv_edge_connectivity) { | if (use_uv_edge_connectivity) { | ||||
| nislands = bm_uv_edge_select_build_islands( | nislands = bm_uv_edge_select_build_islands( | ||||
| element_map, scene, islandbuf, map, uv_selected, cd_loop_uv_offset); | element_map, scene, islandbuf, map, uv_selected, uv_offsets); | ||||
| islandbufsize = totuv; | islandbufsize = totuv; | ||||
| } | } | ||||
| for (int i = 0; i < totuv; i++) { | for (int i = 0; i < totuv; i++) { | ||||
| if (element_map->storage[i].island == INVALID_ISLAND) { | if (element_map->storage[i].island == INVALID_ISLAND) { | ||||
| int stacksize = 0; | int stacksize = 0; | ||||
| element_map->storage[i].island = nislands; | element_map->storage[i].island = nislands; | ||||
| stack[0] = element_map->storage[i].l->f; | stack[0] = element_map->storage[i].l->f; | ||||
| island_number[BM_elem_index_get(stack[0])] = nislands; | island_number[BM_elem_index_get(stack[0])] = nislands; | ||||
| stacksize = 1; | stacksize = 1; | ||||
| while (stacksize > 0) { | while (stacksize > 0) { | ||||
| BMFace *efa = stack[--stacksize]; | BMFace *efa = stack[--stacksize]; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BMIter liter; | BMIter liter; | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| if (uv_selected && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { | if (uv_selected && !uvedit_uv_select_test(scene, l, uv_offsets)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| UvElement *initelement = element_map->vertex[BM_elem_index_get(l->v)]; | UvElement *initelement = element_map->vertex[BM_elem_index_get(l->v)]; | ||||
| for (UvElement *element = initelement; element; element = element->next) { | for (UvElement *element = initelement; element; element = element->next) { | ||||
| if (element->separate) { | if (element->separate) { | ||||
| initelement = element; | initelement = element; | ||||
| ▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | static void bm_uv_build_islands(UvElementMap *element_map, | ||||
| element_map->storage = islandbuf; | element_map->storage = islandbuf; | ||||
| islandbuf = NULL; | islandbuf = NULL; | ||||
| element_map->total_islands = nislands; | element_map->total_islands = nislands; | ||||
| MEM_SAFE_FREE(stack); | MEM_SAFE_FREE(stack); | ||||
| MEM_SAFE_FREE(map); | MEM_SAFE_FREE(map); | ||||
| } | } | ||||
| /* return true if `loop` has UV co-ordinates which match `luv_a` and `luv_b` */ | /* return true if `loop` has UV co-ordinates which match `luv_a` and `luv_b` */ | ||||
| static bool loop_uv_match(BMLoop *loop, MLoopUV *luv_a, MLoopUV *luv_b, int cd_loop_uv_offset) | static bool loop_uv_match(BMLoop *loop, | ||||
| const float luv_a[2], | |||||
| const float luv_b[2], | |||||
| int cd_loop_uv_offset) | |||||
| { | { | ||||
| MLoopUV *luv_c = BM_ELEM_CD_GET_VOID_P(loop, cd_loop_uv_offset); | const float *luv_c = BM_ELEM_CD_GET_FLOAT_P(loop, cd_loop_uv_offset); | ||||
| MLoopUV *luv_d = BM_ELEM_CD_GET_VOID_P(loop->next, cd_loop_uv_offset); | const float *luv_d = BM_ELEM_CD_GET_FLOAT_P(loop->next, cd_loop_uv_offset); | ||||
| return compare_v2v2(luv_a->uv, luv_c->uv, STD_UV_CONNECT_LIMIT) && | return compare_v2v2(luv_a, luv_c, STD_UV_CONNECT_LIMIT) && | ||||
| compare_v2v2(luv_b->uv, luv_d->uv, STD_UV_CONNECT_LIMIT); | compare_v2v2(luv_b, luv_d, STD_UV_CONNECT_LIMIT); | ||||
| } | } | ||||
| /* Given `anchor` and `edge`, return true if there are edges that fan between them that are | /* Given `anchor` and `edge`, return true if there are edges that fan between them that are | ||||
| * seam-free. */ | * seam-free. */ | ||||
| static bool seam_connected_recursive(BMVert *anchor, | static bool seam_connected_recursive(BMVert *anchor, | ||||
| BMEdge *edge, | BMEdge *edge, | ||||
| MLoopUV *luv_anchor, | float luv_anchor[2], | ||||
| MLoopUV *luv_fan, | float luv_fan[2], | ||||
| BMLoop *needle, | BMLoop *needle, | ||||
| GSet *visited, | GSet *visited, | ||||
| int cd_loop_uv_offset) | int cd_loop_uv_offset) | ||||
| { | { | ||||
| BLI_assert(edge->v1 == anchor || edge->v2 == anchor); | BLI_assert(edge->v1 == anchor || edge->v2 == anchor); | ||||
| BLI_assert(needle->v == anchor || needle->next->v == anchor); | BLI_assert(needle->v == anchor || needle->next->v == anchor); | ||||
| if (BM_elem_flag_test(edge, BM_ELEM_SEAM)) { | if (BM_elem_flag_test(edge, BM_ELEM_SEAM)) { | ||||
| Show All 11 Lines | if (loop->v == anchor) { | ||||
| if (!loop_uv_match(loop, luv_anchor, luv_fan, cd_loop_uv_offset)) { | if (!loop_uv_match(loop, luv_anchor, luv_fan, cd_loop_uv_offset)) { | ||||
| continue; /* `loop` is disjoint in UV space. */ | continue; /* `loop` is disjoint in UV space. */ | ||||
| } | } | ||||
| if (loop->prev == needle) { | if (loop->prev == needle) { | ||||
| return true; /* Success. */ | return true; /* Success. */ | ||||
| } | } | ||||
| MLoopUV *luv_far = BM_ELEM_CD_GET_VOID_P(loop->prev, cd_loop_uv_offset); | float *luv_far = BM_ELEM_CD_GET_FLOAT_P(loop->prev, cd_loop_uv_offset); | ||||
| if (seam_connected_recursive( | if (seam_connected_recursive( | ||||
| anchor, loop->prev->e, luv_anchor, luv_far, needle, visited, cd_loop_uv_offset)) { | anchor, loop->prev->e, luv_anchor, luv_far, needle, visited, cd_loop_uv_offset)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(loop->next->v == anchor); | BLI_assert(loop->next->v == anchor); | ||||
| if (!loop_uv_match(loop, luv_fan, luv_anchor, cd_loop_uv_offset)) { | if (!loop_uv_match(loop, luv_fan, luv_anchor, cd_loop_uv_offset)) { | ||||
| continue; /* `loop` is disjoint in UV space. */ | continue; /* `loop` is disjoint in UV space. */ | ||||
| } | } | ||||
| if (loop->next == needle) { | if (loop->next == needle) { | ||||
| return true; /* Success. */ | return true; /* Success. */ | ||||
| } | } | ||||
| MLoopUV *luv_far = BM_ELEM_CD_GET_VOID_P(loop->next->next, cd_loop_uv_offset); | float *luv_far = BM_ELEM_CD_GET_FLOAT_P(loop->next->next, cd_loop_uv_offset); | ||||
| if (seam_connected_recursive( | if (seam_connected_recursive( | ||||
| anchor, loop->next->e, luv_anchor, luv_far, needle, visited, cd_loop_uv_offset)) { | anchor, loop->next->e, luv_anchor, luv_far, needle, visited, cd_loop_uv_offset)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Given `loop_a` and `loop_b` originate from the same vertex and share a UV, | /* Given `loop_a` and `loop_b` originate from the same vertex and share a UV, | ||||
| * return true if there are edges that fan between them that are seam-free. | * return true if there are edges that fan between them that are seam-free. | ||||
| * return false otherwise. | * return false otherwise. | ||||
| */ | */ | ||||
| static bool seam_connected(BMLoop *loop_a, BMLoop *loop_b, GSet *visited, int cd_loop_uv_offset) | static bool seam_connected(BMLoop *loop_a, BMLoop *loop_b, GSet *visited, int cd_loop_uv_offset) | ||||
| { | { | ||||
| BLI_assert(loop_a && loop_b); | BLI_assert(loop_a && loop_b); | ||||
| BLI_assert(loop_a != loop_b); | BLI_assert(loop_a != loop_b); | ||||
| BLI_assert(loop_a->v == loop_b->v); | BLI_assert(loop_a->v == loop_b->v); | ||||
| BLI_gset_clear(visited, NULL); | BLI_gset_clear(visited, NULL); | ||||
| MLoopUV *luv_anchor = BM_ELEM_CD_GET_VOID_P(loop_a, cd_loop_uv_offset); | float *luv_anchor = BM_ELEM_CD_GET_FLOAT_P(loop_a, cd_loop_uv_offset); | ||||
| MLoopUV *luv_fan = BM_ELEM_CD_GET_VOID_P(loop_a->next, cd_loop_uv_offset); | float *luv_fan = BM_ELEM_CD_GET_FLOAT_P(loop_a->next, cd_loop_uv_offset); | ||||
| const bool result = seam_connected_recursive( | const bool result = seam_connected_recursive( | ||||
| loop_a->v, loop_a->e, luv_anchor, luv_fan, loop_b, visited, cd_loop_uv_offset); | loop_a->v, loop_a->e, luv_anchor, luv_fan, loop_b, visited, cd_loop_uv_offset); | ||||
| return result; | return result; | ||||
| } | } | ||||
| UvElementMap *BM_uv_element_map_create(BMesh *bm, | UvElementMap *BM_uv_element_map_create(BMesh *bm, | ||||
| const Scene *scene, | const Scene *scene, | ||||
| const bool uv_selected, | const bool uv_selected, | ||||
| const bool use_winding, | const bool use_winding, | ||||
| const bool use_seams, | const bool use_seams, | ||||
| const bool do_islands) | const bool do_islands) | ||||
| { | { | ||||
| /* In uv sync selection, all UVs are visible. */ | /* In uv sync selection, all UVs are visible. */ | ||||
| const bool face_selected = !(scene->toolsettings->uv_flag & UV_SYNC_SELECTION); | const bool face_selected = !(scene->toolsettings->uv_flag & UV_SYNC_SELECTION); | ||||
| BMVert *ev; | BMVert *ev; | ||||
| BMFace *efa; | BMFace *efa; | ||||
| BMIter iter, liter; | BMIter iter, liter; | ||||
| BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); | BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); | ||||
| MLoopUV *luv; | |||||
| const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); | const BMUVOffsets offsets = BM_uv_map_get_offsets(bm); | ||||
| if (cd_loop_uv_offset < 0) { | if (offsets.uv < 0) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); | BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); | ||||
| /* Count total uvs. */ | /* Count total uvs. */ | ||||
| int totuv = 0; | int totuv = 0; | ||||
| BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { | BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { | ||||
| if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { | if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (face_selected && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | if (face_selected && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (!uv_selected) { | if (!uv_selected) { | ||||
| totuv += efa->len; | totuv += efa->len; | ||||
| } | } | ||||
| else { | else { | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | ||||
| if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { | if (uvedit_uv_select_test(scene, l, offsets)) { | ||||
| totuv++; | totuv++; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (totuv == 0) { | if (totuv == 0) { | ||||
| return NULL; | return NULL; | ||||
| Show All 24 Lines | BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, j) { | ||||
| if (use_winding) { | if (use_winding) { | ||||
| tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa->len); | tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa->len); | ||||
| } | } | ||||
| int i; | int i; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { | BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { | ||||
| if (uv_selected && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { | if (uv_selected && !uvedit_uv_select_test(scene, l, offsets)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| buf->l = l; | buf->l = l; | ||||
| buf->island = INVALID_ISLAND; | buf->island = INVALID_ISLAND; | ||||
| buf->loop_of_poly_index = i; | buf->loop_of_poly_index = i; | ||||
| /* Insert to head of linked list associated with BMVert. */ | /* Insert to head of linked list associated with BMVert. */ | ||||
| buf->next = element_map->vertex[BM_elem_index_get(l->v)]; | buf->next = element_map->vertex[BM_elem_index_get(l->v)]; | ||||
| element_map->vertex[BM_elem_index_get(l->v)] = buf; | element_map->vertex[BM_elem_index_get(l->v)] = buf; | ||||
| if (use_winding) { | if (use_winding) { | ||||
| luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); | const float *uv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); | ||||
| copy_v2_v2(tf_uv[i], luv->uv); | copy_v2_v2(tf_uv[i], uv); | ||||
| } | } | ||||
| buf++; | buf++; | ||||
| } | } | ||||
| if (winding) { | if (winding) { | ||||
| winding[j] = cross_poly_v2(tf_uv, efa->len) > 0; | winding[j] = cross_poly_v2(tf_uv, efa->len) > 0; | ||||
| } | } | ||||
| Show All 10 Lines | BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, ev_index) { | ||||
| while (vlist) { | while (vlist) { | ||||
| /* Detach head from unsorted list. */ | /* Detach head from unsorted list. */ | ||||
| UvElement *v = vlist; | UvElement *v = vlist; | ||||
| vlist = vlist->next; | vlist = vlist->next; | ||||
| v->next = newvlist; | v->next = newvlist; | ||||
| newvlist = v; | newvlist = v; | ||||
| luv = BM_ELEM_CD_GET_VOID_P(v->l, cd_loop_uv_offset); | const float *uv = BM_ELEM_CD_GET_VOID_P(v->l, offsets.uv); | ||||
| const float *uv = luv->uv; | bool uv_vert_sel = uvedit_uv_select_test(scene, v->l, offsets); | ||||
| bool uv_vert_sel = uvedit_uv_select_test(scene, v->l, cd_loop_uv_offset); | |||||
| UvElement *lastv = NULL; | UvElement *lastv = NULL; | ||||
| UvElement *iterv = vlist; | UvElement *iterv = vlist; | ||||
| /* Scan through unsorted list, finding UvElements which are connected to `v`. */ | /* Scan through unsorted list, finding UvElements which are connected to `v`. */ | ||||
| while (iterv) { | while (iterv) { | ||||
| UvElement *next = iterv->next; | UvElement *next = iterv->next; | ||||
| luv = BM_ELEM_CD_GET_VOID_P(iterv->l, cd_loop_uv_offset); | |||||
| bool connected = true; /* Assume connected unless we can prove otherwise. */ | bool connected = true; /* Assume connected unless we can prove otherwise. */ | ||||
| if (connected) { | if (connected) { | ||||
| /* Are the two UVs close together? */ | /* Are the two UVs close together? */ | ||||
| const float *uv2 = luv->uv; | const float *uv2 = BM_ELEM_CD_GET_FLOAT_P(iterv->l, offsets.uv); | ||||
| connected = compare_v2v2(uv2, uv, STD_UV_CONNECT_LIMIT); | connected = compare_v2v2(uv2, uv, STD_UV_CONNECT_LIMIT); | ||||
| } | } | ||||
| if (connected) { | if (connected) { | ||||
| /* Check if the uv loops share the same selection state (if not, they are not connected | /* Check if the uv loops share the same selection state (if not, they are not connected | ||||
| * as they have been ripped or other edit commands have separated them). */ | * as they have been ripped or other edit commands have separated them). */ | ||||
| const bool uv2_vert_sel = uvedit_uv_select_test(scene, iterv->l, cd_loop_uv_offset); | const bool uv2_vert_sel = uvedit_uv_select_test(scene, iterv->l, offsets); | ||||
| connected = (uv_vert_sel == uv2_vert_sel); | connected = (uv_vert_sel == uv2_vert_sel); | ||||
| } | } | ||||
| if (connected && use_winding) { | if (connected && use_winding) { | ||||
| connected = winding[BM_elem_index_get(iterv->l->f)] == | connected = winding[BM_elem_index_get(iterv->l->f)] == | ||||
| winding[BM_elem_index_get(v->l->f)]; | winding[BM_elem_index_get(v->l->f)]; | ||||
| } | } | ||||
| if (connected && use_seams) { | if (connected && use_seams) { | ||||
| connected = seam_connected(iterv->l, v->l, seam_visited_gset, cd_loop_uv_offset); | connected = seam_connected(iterv->l, v->l, seam_visited_gset, offsets.uv); | ||||
| } | } | ||||
| if (connected) { | if (connected) { | ||||
| if (lastv) { | if (lastv) { | ||||
| lastv->next = next; | lastv->next = next; | ||||
| } | } | ||||
| else { | else { | ||||
| vlist = next; | vlist = next; | ||||
| ▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | BMFace *EDBM_uv_active_face_get(BMEditMesh *em, const bool sloppy, const bool selected) | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| bool EDBM_uv_check(BMEditMesh *em) | bool EDBM_uv_check(BMEditMesh *em) | ||||
| { | { | ||||
| /* some of these checks could be a touch overkill */ | /* some of these checks could be a touch overkill */ | ||||
| return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV); | return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_PROP_FLOAT2); | ||||
| } | } | ||||
| bool EDBM_vert_color_check(BMEditMesh *em) | bool EDBM_vert_color_check(BMEditMesh *em) | ||||
| { | { | ||||
| /* some of these checks could be a touch overkill */ | /* some of these checks could be a touch overkill */ | ||||
| return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_PROP_BYTE_COLOR); | return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_PROP_BYTE_COLOR); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 725 Lines • Show Last 20 Lines | |||||