From 57ce6d1470907b283742f45d369b4fe6edcee361 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 22 Jul 2013 14:50:38 +0000 Subject: old todo, rotate around individual origins now supports connected face/edge islands. previously this gave very odd/annoying results, see bug reports [#36134], [#35419] --- source/blender/bmesh/intern/bmesh_queries.c | 205 ++++++++++++++++++--- source/blender/bmesh/intern/bmesh_queries.h | 9 +- source/blender/bmesh/operators/bmo_normals.c | 7 +- source/blender/editors/transform/transform.c | 4 +- .../editors/transform/transform_conversions.c | 203 ++++++++++++++------ 5 files changed, 335 insertions(+), 93 deletions(-) (limited to 'source/blender') diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 720997fcef8..8f5e25f5fd7 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1758,20 +1758,27 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed) return vol; } - +/* note, almost duplicate of BM_mesh_calc_edge_groups, keep in sync */ /** - * TODO (as we need) - * - option to walk over faces by verts. - * - option to walk over non manifold edges. + * Calculate isolated groups of faces with optional filtering. * * \param bm the BMesh. - * \param r_groups_array Array of ints to fill in, length of bm->totface. + * \param r_groups_array Array of ints to fill in, length of bm->totface + * (or when hflag_test is set, the number of flagged faces). * \param r_group_index index, length pairs into \a r_groups_array, size of return value - * int pairs: (array_start, array_length). + * int pairs: (array_start, array_length). + * \param filter_fn Filter the edges or verts we step over (depends on \a htype_step) + * as to which types we deal with. + * \param user_data Optional user data for \a filter_fn, can be NULL. + * \param hflag_test Optional flag to test faces, + * use to exclude faces from the calculation, 0 for all faces. + * \param htype_step BM_VERT to walk over face-verts, BM_EDGE to walk over faces edges + * (having both set is supported too). * \return The number of groups found. */ int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - bool (*filter_fn)(BMElem *, void *user_data), void *user_data, const char htype) + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test, const char htype_step) { #ifdef DEBUG int group_index_len = 1; @@ -1786,11 +1793,11 @@ int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde int group_curr = 0; - const unsigned int tot_faces = bm->totface; + unsigned int tot_faces = 0; unsigned int tot_touch = 0; - BMFace **fstack; - STACK_DECLARE(fstack); + BMFace **stack; + STACK_DECLARE(stack); BMIter iter; BMFace *f; @@ -1798,30 +1805,38 @@ int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde STACK_INIT(group_array); - BLI_assert(((htype & ~(BM_VERT | BM_EDGE)) == 0) && (htype != 0)); + BLI_assert(((htype_step & ~(BM_VERT | BM_EDGE)) == 0) && (htype_step != 0)); /* init the array */ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { + if ((hflag_test == 0) || BM_elem_flag_test(f, hflag_test)) { + tot_faces++; + BM_elem_flag_disable(f, BM_ELEM_TAG); + } + else { + /* never walk over tagged */ + BM_elem_flag_enable(f, BM_ELEM_TAG); + } + BM_elem_index_set(f, i); /* set_inline */ - BM_elem_flag_disable(f, BM_ELEM_TAG); } bm->elem_index_dirty &= ~BM_FACE; /* detect groups */ - fstack = MEM_mallocN(sizeof(*fstack) * tot_faces, __func__); + stack = MEM_mallocN(sizeof(*stack) * tot_faces, __func__); while (tot_touch != tot_faces) { - int *fg; + int *group_item; bool ok = false; BLI_assert(tot_touch < tot_faces); - STACK_INIT(fstack); + STACK_INIT(stack); BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(f, BM_ELEM_TAG) == false) { BM_elem_flag_enable(f, BM_ELEM_TAG); - STACK_PUSH(fstack, f); + STACK_PUSH(stack, f); ok = true; break; } @@ -1835,48 +1850,50 @@ int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len); } - fg = group_index[group_curr]; - fg[0] = STACK_SIZE(group_array); - fg[1] = 0; + group_item = group_index[group_curr]; + group_item[0] = STACK_SIZE(group_array); + group_item[1] = 0; - while ((f = STACK_POP(fstack))) { + while ((f = STACK_POP(stack))) { BMLoop *l_iter, *l_first; /* add face */ STACK_PUSH(group_array, BM_elem_index_get(f)); tot_touch++; - fg[1]++; + group_item[1]++; /* done */ - if (htype & BM_EDGE) { + if (htype_step & BM_EDGE) { /* search for other faces */ l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { BMLoop *l_radial_iter = l_iter->radial_next; - if ((l_radial_iter != l_iter) && filter_fn((BMElem *)l_iter->e, user_data)) { + if ((l_radial_iter != l_iter) && + ((filter_fn == NULL) || filter_fn((BMElem *)l_iter->e, user_data))) + { do { BMFace *f_other = l_radial_iter->f; if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) { BM_elem_flag_enable(f_other, BM_ELEM_TAG); - STACK_PUSH(fstack, f_other); + STACK_PUSH(stack, f_other); } } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter); } } while ((l_iter = l_iter->next) != l_first); } - if (htype & BM_VERT) { + if (htype_step & BM_VERT) { BMIter liter; /* search for other faces */ l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - if (filter_fn((BMElem *)l_iter->v, user_data)) { + if ((filter_fn == NULL) || filter_fn((BMElem *)l_iter->v, user_data)) { BMLoop *l_other; BM_ITER_ELEM (l_other, &liter, l_iter, BM_LOOPS_OF_LOOP) { BMFace *f_other = l_other->f; if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) { BM_elem_flag_enable(f_other, BM_ELEM_TAG); - STACK_PUSH(fstack, f_other); + STACK_PUSH(stack, f_other); } } } @@ -1887,7 +1904,139 @@ int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde group_curr++; } - MEM_freeN(fstack); + MEM_freeN(stack); + + /* reduce alloc to required size */ + group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr); + *r_group_index = group_index; + + return group_curr; +} + +/* note, almost duplicate of BM_mesh_calc_face_groups, keep in sync */ +/** + * Calculate isolated groups of edges with optional filtering. + * + * \param bm the BMesh. + * \param r_groups_array Array of ints to fill in, length of bm->totedge + * (or when hflag_test is set, the number of flagged edges). + * \param r_group_index index, length pairs into \a r_groups_array, size of return value + * int pairs: (array_start, array_length). + * \param filter_fn Filter the edges or verts we step over (depends on \a htype_step) + * as to which types we deal with. + * \param user_data Optional user data for \a filter_fn, can be NULL. + * \param hflag_test Optional flag to test edges, + * use to exclude edges from the calculation, 0 for all edges. + * \return The number of groups found. + * + * \note Unlike #BM_mesh_calc_face_groups there is no 'htype_step' argument, + * since we always walk over verts. + */ +int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test) +{ +#ifdef DEBUG + int group_index_len = 1; +#else + int group_index_len = 32; +#endif + + int (*group_index)[2] = MEM_mallocN(sizeof(*group_index) * group_index_len, __func__); + + int *group_array = r_groups_array; + STACK_DECLARE(group_array); + + int group_curr = 0; + + unsigned int tot_edges = 0; + unsigned int tot_touch = 0; + + BMEdge **stack; + STACK_DECLARE(stack); + + BMIter iter; + BMEdge *e; + int i; + + STACK_INIT(group_array); + + /* init the array */ + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + if ((hflag_test == 0) || BM_elem_flag_test(e, hflag_test)) { + tot_edges++; + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + else { + /* never walk over tagged */ + BM_elem_flag_enable(e, BM_ELEM_TAG); + } + + BM_elem_index_set(e, i); /* set_inline */ + } + bm->elem_index_dirty &= ~BM_FACE; + + /* detect groups */ + stack = MEM_mallocN(sizeof(*stack) * tot_edges, __func__); + + while (tot_touch != tot_edges) { + int *group_item; + bool ok = false; + + BLI_assert(tot_touch < tot_edges); + + STACK_INIT(stack); + + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + STACK_PUSH(stack, e); + ok = true; + break; + } + } + + BLI_assert(ok == true); + + /* manage arrays */ + if (group_index_len == group_curr) { + group_index_len *= 2; + group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len); + } + + group_item = group_index[group_curr]; + group_item[0] = STACK_SIZE(group_array); + group_item[1] = 0; + + while ((e = STACK_POP(stack))) { + BMIter viter; + BMIter eiter; + BMVert *v; + + /* add edge */ + STACK_PUSH(group_array, BM_elem_index_get(e)); + tot_touch++; + group_item[1]++; + /* done */ + + /* search for other edges */ + BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) { + if ((filter_fn == NULL) || filter_fn((BMElem *)v, user_data)) { + BMEdge *e_other; + BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e_other, BM_ELEM_TAG) == false) { + BM_elem_flag_enable(e_other, BM_ELEM_TAG); + STACK_PUSH(stack, e_other); + } + } + } + } + } + + group_curr++; + } + + MEM_freeN(stack); /* reduce alloc to required size */ group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr); diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index f62de692778..23d89cf92fa 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -27,6 +27,8 @@ * \ingroup bmesh */ +typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data); + bool BM_vert_in_face(BMFace *f, BMVert *v); int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len); bool BM_verts_in_face(BMFace *f, BMVert **varr, int len); @@ -115,8 +117,13 @@ bool BM_face_is_any_vert_flag_test(BMFace *f, const char hflag); bool BM_face_is_any_edge_flag_test(BMFace *f, const char hflag); float BM_mesh_calc_volume(BMesh *bm, bool is_signed); + int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - bool (*filter_fn)(BMElem *, void *user_data), void *user_data, const char htype); + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test, const char htype_step); +int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test); /* not really any good place to put this */ float bmesh_subd_falloff_calc(const int falloff, float val); diff --git a/source/blender/bmesh/operators/bmo_normals.c b/source/blender/bmesh/operators/bmo_normals.c index 9d86e7ab275..025b8557331 100644 --- a/source/blender/bmesh/operators/bmo_normals.c +++ b/source/blender/bmesh/operators/bmo_normals.c @@ -146,14 +146,15 @@ static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int f void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) { - int *groups_array = MEM_mallocN(sizeof(groups_array) * bm->totface, __func__); + int *groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totface, __func__); int faces_len; BMFace **faces_arr = BM_iter_as_arrayN(bm, BM_FACES_OF_MESH, NULL, &faces_len, NULL, 0); - BMFace **faces_grp = MEM_mallocN(sizeof(faces_grp) * bm->totface, __func__); + BMFace **faces_grp = MEM_mallocN(sizeof(*faces_grp) * bm->totface, __func__); int (*group_index)[2]; const int group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index, - bmo_recalc_normal_edge_filter_cb, NULL, BM_EDGE); + bmo_recalc_normal_edge_filter_cb, NULL, + 0, BM_EDGE); int i; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index a565213f031..b15470c98c9 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -111,9 +111,7 @@ static bool transdata_check_local_center(TransInfo *t) { return ((t->around == V3D_LOCAL) && ( (t->flag & (T_OBJECT | T_POSE)) || - (t->obedit && t->obedit->type == OB_MESH && (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE))) || - (t->obedit && t->obedit->type == OB_MBALL) || - (t->obedit && t->obedit->type == OB_ARMATURE) || + (t->obedit && ELEM3(t->obedit->type, OB_MESH, OB_MBALL, OB_ARMATURE)) || (t->spacetype == SPACE_IPO)) ); } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 93e01d84eaf..977a9b88fc8 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -124,6 +124,11 @@ #include "BLI_sys_types.h" // for intptr_t support +/* when transforming islands */ +struct TransIslandData { + float co[3]; + float axismtx[3][3]; +}; /* local function prototype - for Object/Bone Constraints */ static bool constraints_list_needinv(TransInfo *t, ListBase *list); @@ -1914,34 +1919,124 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float MEM_freeN(dists_prev); } -static BMElem *bm_vert_single_select_face(BMVert *eve) +static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r_island_tot, int **r_island_vert_map) { - BMElem *ele; - BMIter iter; + BMesh *bm = em->bm; + struct TransIslandData *trans_islands; + char htype; + char itype; + int i; + + /* group vars */ + int *groups_array; + int (*group_index)[2]; + int group_tot; + void **ele_array; + + int *vert_map; + + if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) { + groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__); + group_tot = BM_mesh_calc_edge_groups(bm, groups_array, &group_index, + NULL, NULL, + BM_ELEM_SELECT); + + htype = BM_EDGE; + itype = BM_VERTS_OF_EDGE; - BM_ITER_ELEM (ele, &iter, eve, BM_FACES_OF_VERT) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - return ele; - } } - return NULL; -} -static BMElem *bm_vert_single_select_edge(BMVert *eve) -{ - BMElem *ele; - BMIter iter; + else { /* (bm->selectmode & SCE_SELECT_FACE) */ + groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__); + group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index, + NULL, NULL, + BM_ELEM_SELECT, BM_VERT); + + htype = BM_FACE; + itype = BM_VERTS_OF_FACE; + } + + + trans_islands = MEM_mallocN(sizeof(*trans_islands) * group_tot, __func__); - BM_ITER_ELEM (ele, &iter, eve, BM_EDGES_OF_VERT) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - return ele; + vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__); + /* we shouldn't need this, but with incorrect selection flushing + * its possible we have a selected vertex thats not in a face, for now best not crash in that case. */ + fill_vn_i(vert_map, bm->totvert, -1); + + EDBM_index_arrays_ensure(em, htype); + ele_array = (htype == BM_FACE) ? (void **)em->face_index : (void **)em->edge_index; + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + /* may be an edge OR a face array */ + for (i = 0; i < group_tot; i++) { + BMEditSelection ese = {0}; + + const int fg_sta = group_index[i][0]; + const int fg_len = group_index[i][1]; + float co[3], no[3], tangent[3]; + int j; + + zero_v3(co); + zero_v3(no); + zero_v3(tangent); + + ese.htype = htype; + + /* loop on each face in this group: + * - assign r_vert_map + * - calculate (co, no) + */ + for (j = 0; j < fg_len; j++) { + float tmp_co[3], tmp_no[3], tmp_tangent[3]; + + ese.ele = ele_array[groups_array[fg_sta + j]]; + + BM_editselection_center(&ese, tmp_co); + BM_editselection_normal(&ese, tmp_no); + BM_editselection_plane(&ese, tmp_tangent); + + add_v3_v3(co, tmp_co); + add_v3_v3(no, tmp_no); + add_v3_v3(tangent, tmp_tangent); + + { + /* setup vertex map */ + BMIter iter; + BMVert *v; + + /* connected edge-verts */ + BM_ITER_ELEM (v, &iter, ese.ele, itype) { + vert_map[BM_elem_index_get(v)] = i; + } + } + } + + mul_v3_v3fl(trans_islands[i].co, co, 1.0f / (float)fg_len); + + if (createSpaceNormalTangent(trans_islands[i].axismtx, no, tangent)) { + /* pass */ + } + else { + normalize_v3(no); + axis_dominant_v3_to_m3(trans_islands[i].axismtx, no); + invert_m3(trans_islands[i].axismtx); } } - return NULL; + + MEM_freeN(groups_array); + MEM_freeN(group_index); + + *r_island_tot = group_tot; + *r_island_vert_map = vert_map; + + return trans_islands; } /* way to overwrite what data is edited with transform */ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx, - BMEditMesh *em, BMVert *eve, float *bweight) + BMEditMesh *em, BMVert *eve, float *bweight, + struct TransIslandData *v_island) { BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0); @@ -1951,40 +2046,20 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx //else td->loc = eve->co; copy_v3_v3(td->iloc, td->loc); - copy_v3_v3(td->center, td->loc); - if (t->around == V3D_LOCAL) { - BMElem *ele; - bool is_axismat_set = false; - - if (em->selectmode & (SCE_SELECT_FACE | SCE_SELECT_EDGE) && - (ele = ((em->selectmode & SCE_SELECT_FACE) ? - bm_vert_single_select_face(eve) : - bm_vert_single_select_edge(eve)))) - { - float normal[3], tangent[3]; - - BMEditSelection ese; - ese.next = ese.prev = NULL; - ese.ele = ele; - ese.htype = ele->head.htype; - - BM_editselection_center(&ese, td->center); - BM_editselection_normal(&ese, normal); - BM_editselection_plane(&ese, tangent); - - if (createSpaceNormalTangent(td->axismtx, normal, tangent)) { - is_axismat_set = true; - } - } + if (v_island) { + copy_v3_v3(td->center, v_island->co); + copy_m3_m3(td->axismtx, v_island->axismtx); + } + else if (t->around == V3D_LOCAL) { + copy_v3_v3(td->center, td->loc); - /* for verts or fallback when createSpaceNormalTangent fails */ - if (is_axismat_set == false) { - axis_dominant_v3_to_m3(td->axismtx, eve->no); - invert_m3(td->axismtx); - } + axis_dominant_v3_to_m3(td->axismtx, eve->no); + invert_m3(td->axismtx); } else { + copy_v3_v3(td->center, td->loc); + /* Setting normals */ copy_v3_v3(td->axismtx[2], eve->no); td->axismtx[0][0] = @@ -2021,7 +2096,6 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx static void createTransEditVerts(TransInfo *t) { - ToolSettings *ts = t->scene->toolsettings; TransData *tob = NULL; TransDataExtension *tx = NULL; BMEditMesh *em = BKE_editmesh_from_object(t->obedit); @@ -2036,12 +2110,12 @@ static void createTransEditVerts(TransInfo *t) int count = 0, countsel = 0, a, totleft; int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; int mirror = 0; - short selectmode = ts->selectmode; int cd_vert_bweight_offset = -1; bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; - /* BMESH_TODO, writing into the index values is BAD!, means we cant - * use the values for vertex mirror - campbell */ + struct TransIslandData *island_info = NULL; + int island_info_tot; + int *island_vert_map = NULL; if (t->flag & T_MIRROR) { EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology); @@ -2050,17 +2124,17 @@ static void createTransEditVerts(TransInfo *t) /* quick check if we can transform */ /* note: in prop mode we need at least 1 selected */ - if (selectmode & SCE_SELECT_VERTEX) { + if (em->selectmode & SCE_SELECT_VERTEX) { if (bm->totvertsel == 0) { goto cleanup; } } - else if (selectmode & SCE_SELECT_EDGE) { + else if (em->selectmode & SCE_SELECT_EDGE) { if (bm->totvertsel == 0 || bm->totedgesel == 0) { goto cleanup; } } - else if (selectmode & SCE_SELECT_FACE) { + else if (em->selectmode & SCE_SELECT_FACE) { if (bm->totvertsel == 0 || bm->totfacesel == 0) { goto cleanup; } @@ -2112,6 +2186,13 @@ static void createTransEditVerts(TransInfo *t) editmesh_set_connectivity_distance(em->bm, mtx, dists); } + if (t->around == V3D_LOCAL) { + island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map); + } + + /* BMESH_TODO, crazy-space writing into the index values is BAD!, means we cant + * use the values for vertex mirror - campbell */ + /* detect CrazySpace [tm] */ if (modifiers_getCageIndex(t->scene, t->obedit, NULL, 1) >= 0) { if (modifiers_isCorrectableDeformed(t->obedit)) { @@ -2151,9 +2232,11 @@ static void createTransEditVerts(TransInfo *t) BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { if (propmode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ? + &island_info[island_vert_map[a]] : NULL; float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL; - - VertsToTransData(t, tob, tx, em, eve, bweight); + + VertsToTransData(t, tob, tx, em, eve, bweight, v_island); if (tx) tx++; @@ -2213,6 +2296,11 @@ static void createTransEditVerts(TransInfo *t) } } + if (island_info) { + MEM_freeN(island_info); + MEM_freeN(island_vert_map); + } + if (mirror != 0) { tob = t->data; for (a = 0; a < t->total; a++, tob++) { @@ -2233,7 +2321,6 @@ cleanup: if (t->flag & T_MIRROR) { EDBM_verts_mirror_cache_end(em); - mirror = 1; } } -- cgit v1.2.3