old todo, rotate around individual origins now supports connected face/edge islands.
previously this gave very odd/annoying results, see bug reports [#36134], [#35419]
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
BM_ITER_ELEM (ele, &iter, eve, BM_FACES_OF_VERT) {
|
||||
if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
|
||||
return ele;
|
||||
/* 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;
|
||||
|
||||
}
|
||||
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__);
|
||||
|
||||
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;
|
||||
}
|
||||
static BMElem *bm_vert_single_select_edge(BMVert *eve)
|
||||
{
|
||||
BMElem *ele;
|
||||
BMIter iter;
|
||||
|
||||
BM_ITER_ELEM (ele, &iter, eve, BM_EDGES_OF_VERT) {
|
||||
if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
|
||||
return ele;
|
||||
}
|
||||
}
|
||||
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 (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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user