diff options
Diffstat (limited to 'source/blender/editors/transform/transform_conversions.c')
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 170 |
1 files changed, 130 insertions, 40 deletions
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index b68b3365e46..c09434a3bc9 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -286,13 +286,13 @@ static void set_prop_dist(TransInfo *t, const bool with_dist) static void createTransTexspace(TransInfo *t) { - Scene *scene = t->scene; + SceneLayer *sl = t->sl; TransData *td; Object *ob; ID *id; short *texflag; - ob = OBACT; + ob = OBACT_NEW; if (ob == NULL) { // Shouldn't logically happen, but still... t->total = 0; @@ -1800,7 +1800,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) Base *base = CTX_data_active_base(C); Object *ob = CTX_data_active_object(C); ParticleEditSettings *pset = PE_settings(t->scene); - PTCacheEdit *edit = PE_get_current(t->scene, ob); + PTCacheEdit *edit = PE_get_current(t->scene, t->sl, ob); ParticleSystem *psys = NULL; ParticleSystemModifierData *psmd = NULL; PTCacheEditPoint *point; @@ -1917,8 +1917,9 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) void flushTransParticles(TransInfo *t) { Scene *scene = t->scene; - Object *ob = OBACT; - PTCacheEdit *edit = PE_get_current(scene, ob); + SceneLayer *sl = t->sl; + Object *ob = OBACT_NEW; + PTCacheEdit *edit = PE_get_current(scene, sl, ob); ParticleSystem *psys = edit->psys; ParticleSystemModifierData *psmd = NULL; PTCacheEditPoint *point; @@ -1957,14 +1958,17 @@ void flushTransParticles(TransInfo *t) point->flag |= PEP_EDIT_RECALC; } - PE_update_object(scene, OBACT, 1); + PE_update_object(scene, sl, OBACT_NEW, 1); } /* ********************* mesh ****************** */ -static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, - float *dists, const float *dists_prev, - float mtx[3][3]) +static bool bmesh_test_dist_add( + BMVert *v, BMVert *v_other, + float *dists, const float *dists_prev, + /* optionally track original index */ + int *index, const int *index_prev, + float mtx[3][3]) { if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) && (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) @@ -1979,6 +1983,9 @@ static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, dist_other = dists_prev[i] + len_v3(vec); if (dist_other < dists[i_other]) { dists[i_other] = dist_other; + if (index != NULL) { + index[i_other] = index_prev[i]; + } return true; } } @@ -1986,11 +1993,13 @@ static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, return false; } -static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists) +/** + * \parm mtx: Measure disatnce in this space. + * \parm dists: Store the closest connected distance to selected vertices. + * \parm index: Optionally store the original index we're measuring the distance to (can be NULL). + */ +static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists, int *index) { - /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ - float *dists_prev = MEM_mallocN(bm->totvert * sizeof(float), __func__); - BLI_LINKSTACK_DECLARE(queue, BMVert *); /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */ @@ -2011,17 +2020,27 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { dist = FLT_MAX; + if (index != NULL) { + index[i] = i; + } } else { BLI_LINKSTACK_PUSH(queue, v); dist = 0.0f; + if (index != NULL) { + index[i] = i; + } } - dists[i] = dists_prev[i] = dist; + dists[i] = dist; } bm->elem_index_dirty &= ~BM_VERT; } + /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ + float *dists_prev = MEM_dupallocN(dists); + int *index_prev = MEM_dupallocN(index); /* may be NULL */ + do { BMVert *v; LinkNode *lnk; @@ -2050,7 +2069,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float /* edge distance */ { BMVert *v_other = BM_edge_other_vert(e_iter, v); - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { + if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { BM_elem_flag_enable(v_other, BM_ELEM_TAG); BLI_LINKSTACK_PUSH(queue_next, v_other); @@ -2075,7 +2094,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0)) { BMVert *v_other = l_iter_radial->next->next->v; - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { + if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { BM_elem_flag_enable(v_other, BM_ELEM_TAG); BLI_LINKSTACK_PUSH(queue_next, v_other); @@ -2099,6 +2118,9 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float /* keep in sync, avoid having to do full memcpy each iteration */ dists_prev[i] = dists[i]; + if (index != NULL) { + index_prev[i] = index[i]; + } } BLI_LINKSTACK_SWAP(queue, queue_next); @@ -2112,9 +2134,14 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float BLI_LINKSTACK_FREE(queue_next); MEM_freeN(dists_prev); + if (index_prev != NULL) { + MEM_freeN(index_prev); + } } -static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r_island_tot, int **r_island_vert_map) +static struct TransIslandData *editmesh_islands_info_calc( + BMEditMesh *em, int *r_island_tot, int **r_island_vert_map, + bool calc_single_islands) { BMesh *bm = em->bm; struct TransIslandData *trans_islands; @@ -2226,6 +2253,42 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r MEM_freeN(groups_array); MEM_freeN(group_index); + /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */ + if (calc_single_islands) { + BMIter viter; + BMVert *v; + int group_tot_single = 0; + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { + group_tot_single += 1; + } + } + + if (group_tot_single != 0) { + trans_islands = MEM_reallocN(trans_islands, group_tot + group_tot_single); + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { + struct TransIslandData *v_island = &trans_islands[group_tot]; + vert_map[i] = group_tot; + + copy_v3_v3(v_island->co, v->co); + + if (is_zero_v3(v->no) != 0.0f) { + axis_dominant_v3_to_m3(v_island->axismtx, v->no); + invert_m3(v_island->axismtx); + } + else { + unit_m3(v_island->axismtx); + } + + group_tot += 1; + } + } + } + } + *r_island_tot = group_tot; *r_island_vert_map = vert_map; @@ -2325,6 +2388,11 @@ static void createTransEditVerts(TransInfo *t) int island_info_tot; int *island_vert_map = NULL; + const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION); + /* Original index of our connected vertex when connected distances are calculated. + * Optional, allocate if needed. */ + int *dists_index = NULL; + if (t->flag & T_MIRROR) { EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology); mirror = 1; @@ -2356,8 +2424,12 @@ static void createTransEditVerts(TransInfo *t) t->total = count; /* allocating scratch arrays */ - if (prop_mode & T_PROP_CONNECTED) - dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears"); + if (prop_mode & T_PROP_CONNECTED) { + dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__); + if (is_island_center) { + dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__); + } + } } else { t->total = bm->totvertsel; @@ -2379,7 +2451,7 @@ static void createTransEditVerts(TransInfo *t) pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); if (prop_mode & T_PROP_CONNECTED) { - editmesh_set_connectivity_distance(em->bm, mtx, dists); + editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index); } /* Only in case of rotation and resize, we want the elements of the edited @@ -2387,8 +2459,14 @@ static void createTransEditVerts(TransInfo *t) * * TODO: use island_info to detect the closest point when the "Snap Target" * in Blender UI is "Closest" */ - if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION)) { - island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map); + if (is_island_center) { + /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */ + const bool calc_single_islands = ( + (prop_mode & T_PROP_CONNECTED) && + (t->around == V3D_AROUND_LOCAL_ORIGINS) && + (em->selectmode & SCE_SELECT_VERTEX)); + + island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map, calc_single_islands); } /* detect CrazySpace [tm] */ @@ -2438,10 +2516,16 @@ 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 (prop_mode || 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; + struct TransIslandData *v_island = NULL; float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL; + if (island_info) { + const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a; + v_island = (island_vert_map[connected_index] != -1) ? + &island_info[island_vert_map[connected_index]] : NULL; + } + + VertsToTransData(t, tob, tx, em, eve, bweight, v_island); if (tx) tx++; @@ -2520,6 +2604,8 @@ cleanup: MEM_freeN(defmats); if (dists) MEM_freeN(dists); + if (dists_index) + MEM_freeN(dists_index); if (t->flag & T_MIRROR) { EDBM_verts_mirror_cache_end(em); @@ -5523,7 +5609,7 @@ static void clear_trans_object_base_flags(TransInfo *t) * tmode: should be a transform mode */ // NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases -void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, int tmode) +void autokeyframe_ob_cb_func(bContext *C, Scene *scene, SceneLayer *sl, View3D *v3d, Object *ob, int tmode) { ID *id = &ob->id; FCurve *fcu; @@ -5572,7 +5658,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, } else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) { if (v3d->around == V3D_AROUND_ACTIVE) { - if (ob != OBACT) + if (ob != OBACT_NEW) do_loc = true; } else if (v3d->around == V3D_AROUND_CURSOR) @@ -5583,7 +5669,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, } else if (tmode == TFM_RESIZE) { if (v3d->around == V3D_AROUND_ACTIVE) { - if (ob != OBACT) + if (ob != OBACT_NEW) do_loc = true; } else if (v3d->around == V3D_AROUND_CURSOR) @@ -6302,10 +6388,10 @@ void special_aftertrans_update(bContext *C, TransInfo *t) else if (t->options & CTX_PAINT_CURVE) { /* pass */ } - else if ((t->scene->basact) && - (ob = t->scene->basact->object) && + else if ((t->sl->basact) && + (ob = t->sl->basact->object) && (ob->mode & OB_MODE_PARTICLE_EDIT) && - PE_get_current(t->scene, ob)) + PE_get_current(t->scene, t->sl, ob)) { /* do nothing */ } @@ -6346,7 +6432,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) /* Set autokey if necessary */ if (!canceled) { - autokeyframe_ob_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode); + autokeyframe_ob_cb_func(C, t->scene, t->sl, (View3D *)t->view, ob, t->mode); } /* restore rigid body transform */ @@ -6381,8 +6467,6 @@ int special_transform_moving(TransInfo *t) static void createTransObject(bContext *C, TransInfo *t) { - Scene *scene = t->scene; - TransData *td = NULL; TransDataExtension *tx; const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; @@ -6432,15 +6516,16 @@ static void createTransObject(bContext *C, TransInfo *t) CTX_DATA_END; if (is_prop_edit) { - View3D *v3d = t->view; - BaseLegacy *base; + SceneLayer *sl = t->sl; + Base *base; - for (base = scene->base.first; base; base = base->next) { + for (base = sl->object_bases.first; base; base = base->next) { Object *ob = base->object; /* if base is not selected, not a parent of selection or not a child of selection and it is editable */ - if ((ob->flag & (SELECT | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && - BASE_EDITABLE_BGMODE(v3d, scene, base)) + if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 && + (base->flag & BASE_SELECTED) == 0 && + BASE_EDITABLE_BGMODE_NEW(base)) { td->protectflag = ob->protectflag; td->ext = tx; @@ -8021,7 +8106,12 @@ void createTransData(bContext *C, TransInfo *t) if (t->data && t->flag & T_PROP_EDIT) { if (ELEM(t->obedit->type, OB_CURVE, OB_MESH)) { sort_trans_data(t); // makes selected become first in array - set_prop_dist(t, 0); + if ((t->obedit->type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) { + /* already calculated by editmesh_set_connectivity_distance */ + } + else { + set_prop_dist(t, 0); + } sort_trans_data_dist(t); } else { @@ -8057,7 +8147,7 @@ void createTransData(bContext *C, TransInfo *t) } } - else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) { + else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, sl, ob))) { createTransParticleVerts(C, t); t->flag |= T_POINTS; |