diff options
Diffstat (limited to 'source/blender/editors/transform/transform_conversions.c')
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 322 |
1 files changed, 251 insertions, 71 deletions
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index ce3d903b8f6..9d63afeb85c 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -771,29 +771,37 @@ int count_set_pose_transflags(int *out_mode, short around, Object *ob) /* -------- Auto-IK ---------- */ /* adjust pose-channel's auto-ik chainlen */ -static void pchan_autoik_adjust(bPoseChannel *pchan, short chainlen) +static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen) { bConstraint *con; + bool changed = false; /* don't bother to search if no valid constraints */ - if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) - return; + if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) { + return changed; + } /* check if pchan has ik-constraint */ for (con = pchan->constraints.first; con; con = con->next) { if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) { bKinematicConstraint *data = con->data; - + /* only accept if a temporary one (for auto-ik) */ if (data->flag & CONSTRAINT_IK_TEMP) { /* chainlen is new chainlen, but is limited by maximum chainlen */ - if ((chainlen == 0) || (chainlen > data->max_rootbone)) + const int old_rootbone = data->rootbone; + if ((chainlen == 0) || (chainlen > data->max_rootbone)) { data->rootbone = data->max_rootbone; - else + } + else { data->rootbone = chainlen; + } + changed |= (data->rootbone != old_rootbone); } } } + + return changed; } /* change the chain-length of auto-ik */ @@ -809,7 +817,13 @@ void transform_autoik_update(TransInfo *t, short mode) } else if (mode == -1) { /* mode==-1 is from WHEELMOUSEUP... decreases len */ - if (*chainlen > 0) (*chainlen)--; + if (*chainlen > 0) { + (*chainlen)--; + } + else { + /* IK length did not change, skip updates. */ + return; + } } /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */ @@ -817,8 +831,19 @@ void transform_autoik_update(TransInfo *t, short mode) return; /* apply to all pose-channels */ + bool changed = false; for (pchan = t->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) { - pchan_autoik_adjust(pchan, *chainlen); + changed |= pchan_autoik_adjust(pchan, *chainlen); + } + +#ifdef WITH_LEGACY_DEPSGRAPH + if (!DEG_depsgraph_use_legacy()) +#endif + { + if (changed) { + /* TODO(sergey): Consider doing partial update only. */ + DAG_relations_tag_update(G.main); + } } } @@ -828,7 +853,9 @@ static void pose_grab_with_ik_clear(Object *ob) bKinematicConstraint *data; bPoseChannel *pchan; bConstraint *con, *next; +#ifdef WITH_LEGACY_DEPSGRAPH bool need_dependency_update = false; +#endif for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { /* clear all temporary lock flags */ @@ -843,7 +870,9 @@ static void pose_grab_with_ik_clear(Object *ob) data = con->data; if (data->flag & CONSTRAINT_IK_TEMP) { /* iTaSC needs clear for removed constraints */ +#ifdef WITH_LEGACY_DEPSGRAPH need_dependency_update = true; +#endif BIK_clear_data(ob->pose); BLI_remlink(&pchan->constraints, con); @@ -1496,6 +1525,48 @@ static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struc return hdata; } +/** + * For the purpose of transform code we need to behave as if handles are selected, + * even when they aren't (see special case below). + */ +static int bezt_select_to_transform_triple_flag( + const BezTriple *bezt, const bool hide_handles) +{ + int flag = 0; + + if (hide_handles) { + if (bezt->f2 & SELECT) { + flag = (1 << 0) | (1 << 1) | (1 << 2); + } + } + else { + flag = ( + ((bezt->f1 & SELECT) ? (1 << 0) : 0) | + ((bezt->f2 & SELECT) ? (1 << 1) : 0) | + ((bezt->f3 & SELECT) ? (1 << 2) : 0) + ); + } + + /* Special case for auto & aligned handles: + * When a center point is being moved without the handles, + * leaving the handles stationary makes no sense and only causes strange behavior, + * where one handle is arbitrarily anchored, the other one is aligned and lengthened + * based on where the center point is moved. Also a bug when cancelling, see: T52007. + * + * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'. + * However that doesn't resolve odd behavior, so best transform the handles in this case. + */ + if ((flag != ((1 << 0) | (1 << 1) | (1 << 2))) && (flag & (1 << 1))) { + if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) && + ELEM(bezt->h2, HD_AUTO, HD_ALIGN)) + { + flag = (1 << 0) | (1 << 1) | (1 << 2); + } + } + + return flag; +} + static void createTransCurveVerts(TransInfo *t) { Curve *cu = t->obedit->data; @@ -1513,22 +1584,22 @@ static void createTransCurveVerts(TransInfo *t) /* to be sure */ if (cu->editnurb == NULL) return; +#define SEL_F1 (1 << 0) +#define SEL_F2 (1 << 1) +#define SEL_F3 (1 << 2) + /* count total of vertices, check identical as in 2nd loop for making transdata! */ nurbs = BKE_curve_editNurbs_get(cu); for (nu = nurbs->first; nu; nu = nu->next) { if (nu->type == CU_BEZIER) { for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { if (bezt->hide == 0) { - if (hide_handles) { - if (bezt->f2 & SELECT) countsel += 3; - if (is_prop_edit) count += 3; - } - else { - if (bezt->f1 & SELECT) countsel++; - if (bezt->f2 & SELECT) countsel++; - if (bezt->f3 & SELECT) countsel++; - if (is_prop_edit) count += 3; - } + const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles); + if (bezt_tx & SEL_F1) { countsel++; } + if (bezt_tx & SEL_F2) { countsel++; } + if (bezt_tx & SEL_F3) { countsel++; } + if (is_prop_edit) count += 3; + } } } @@ -1579,10 +1650,10 @@ static void createTransCurveVerts(TransInfo *t) } } - if (is_prop_edit || - ((bezt->f2 & SELECT) && hide_handles) || - ((bezt->f1 & SELECT) && hide_handles == 0)) - { + /* Elements that will be transform (not always a match to selection). */ + const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles); + + if (is_prop_edit || bezt_tx & SEL_F1) { copy_v3_v3(td->iloc, bezt->vec[0]); td->loc = bezt->vec[0]; copy_v3_v3(td->center, bezt->vec[(hide_handles || @@ -1613,7 +1684,7 @@ static void createTransCurveVerts(TransInfo *t) } /* This is the Curve Point, the other two are handles */ - if (is_prop_edit || (bezt->f2 & SELECT)) { + if (is_prop_edit || bezt_tx & SEL_F2) { copy_v3_v3(td->iloc, bezt->vec[1]); td->loc = bezt->vec[1]; copy_v3_v3(td->center, td->loc); @@ -1639,7 +1710,7 @@ static void createTransCurveVerts(TransInfo *t) copy_m3_m3(td->axismtx, axismtx); } - if ((bezt->f1 & SELECT) == 0 && (bezt->f3 & SELECT) == 0) + if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0) /* If the middle is selected but the sides arnt, this is needed */ if (hdata == NULL) { /* if the handle was not saved by the previous handle */ hdata = initTransDataCurveHandles(td, bezt); @@ -1649,10 +1720,7 @@ static void createTransCurveVerts(TransInfo *t) count++; tail++; } - if (is_prop_edit || - ((bezt->f2 & SELECT) && hide_handles) || - ((bezt->f3 & SELECT) && hide_handles == 0)) - { + if (is_prop_edit || bezt_tx & SEL_F3) { copy_v3_v3(td->iloc, bezt->vec[2]); td->loc = bezt->vec[2]; copy_v3_v3(td->center, bezt->vec[(hide_handles || @@ -1707,6 +1775,26 @@ static void createTransCurveVerts(TransInfo *t) for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) { if (bp->hide == 0) { if (is_prop_edit || (bp->f1 & SELECT)) { + float axismtx[3][3]; + + if (t->around == V3D_AROUND_LOCAL_ORIGINS) { + if (nu->pntsv == 1) { + float normal[3], plane[3]; + + BKE_nurb_bpoint_calc_normal(nu, bp, normal); + BKE_nurb_bpoint_calc_plane(nu, bp, plane); + + if (createSpaceNormalTangent(axismtx, normal, plane)) { + /* pass */ + } + else { + normalize_v3(normal); + axis_dominant_v3_to_m3(axismtx, normal); + invert_m3(axismtx); + } + } + } + copy_v3_v3(td->iloc, bp->vec); td->loc = bp->vec; copy_v3_v3(td->center, td->loc); @@ -1725,6 +1813,11 @@ static void createTransCurveVerts(TransInfo *t) copy_m3_m3(td->smtx, smtx); copy_m3_m3(td->mtx, mtx); + if (t->around == V3D_AROUND_LOCAL_ORIGINS) { + if (nu->pntsv == 1) { + copy_m3_m3(td->axismtx, axismtx); + } + } td++; count++; @@ -1740,6 +1833,10 @@ static void createTransCurveVerts(TransInfo *t) calc_distanceCurveVerts(head, tail - 1); } } + +#undef SEL_F1 +#undef SEL_F2 +#undef SEL_F3 } /* ********************* lattice *************** */ @@ -1973,9 +2070,12 @@ void flushTransParticles(TransInfo *t) /* ********************* 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)) @@ -1990,6 +2090,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; } } @@ -1997,11 +2100,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) +/** + * \param mtx: Measure disatnce in this space. + * \param dists: Store the closest connected distance to selected vertices. + * \param 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 */ @@ -2022,17 +2127,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; @@ -2061,7 +2176,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); @@ -2086,7 +2201,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); @@ -2110,6 +2225,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); @@ -2123,9 +2241,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; @@ -2237,6 +2360,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, sizeof(*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; @@ -2336,6 +2495,12 @@ static void createTransEditVerts(TransInfo *t) int island_info_tot; int *island_vert_map = NULL; + /* Even for translation this is needed because of island-orientation, see: T51651. */ + const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS); + /* 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; @@ -2367,8 +2532,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; @@ -2390,11 +2559,17 @@ 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); } - if (t->around == V3D_AROUND_LOCAL_ORIGINS) { - 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] */ @@ -2444,10 +2619,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++; @@ -2526,6 +2707,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); @@ -2618,7 +2801,7 @@ void flushTransSeq(TransInfo *t) tdsq = (TransDataSeq *)td->extra; seq = tdsq->seq; old_start = seq->start; - new_frame = iroundf(td2d->loc[0]); + new_frame = round_fl_to_int(td2d->loc[0]); switch (tdsq->sel_flag) { case SELECT: @@ -2630,7 +2813,7 @@ void flushTransSeq(TransInfo *t) seq->start = new_frame - tdsq->start_offset; #endif if (seq->depth == 0) { - seq->machine = iroundf(td2d->loc[1]); + seq->machine = round_fl_to_int(td2d->loc[1]); CLAMP(seq->machine, 1, MAXSEQ); } break; @@ -3578,7 +3761,7 @@ void flushTransIntFrameActionData(TransInfo *t) /* flush data! */ for (i = 0; i < t->total; i++, tfd++) { - *(tfd->sdata) = iroundf(tfd->val); + *(tfd->sdata) = round_fl_to_int(tfd->val); } } @@ -4606,7 +4789,7 @@ void flushTransGraphData(TransInfo *t) /* if int-values only, truncate to integers */ if (td->flag & TD_INTVALUES) - td2d->loc2d[1] = floorf(td2d->loc[1] + 0.5f); + td2d->loc2d[1] = floorf(td2d->loc[1] * inv_unit_scale - tdg->offset + 0.5f); else td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale - tdg->offset; @@ -5259,7 +5442,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) } /* update object's loc/rot to get current rigid body transform */ mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat); - BKE_object_mat3_to_rot(ob, rot, false); + sub_v3_v3(ob->loc, ob->dloc); + BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */ } } @@ -5422,9 +5606,7 @@ static void set_trans_object_base_flags(TransInfo *t) } /* all recalc flags get flushed to all layers, so a layer flip later on works fine */ -#ifdef WITH_LEGACY_DEPSGRAPH DAG_scene_flush_update(G.main, t->scene, -1, 0); -#endif /* and we store them temporal in base (only used for transform code) */ /* this because after doing updates, the object->recalc is cleared */ @@ -5503,9 +5685,7 @@ static int count_proportional_objects(TransInfo *t) /* all recalc flags get flushed to all layers, so a layer flip later on works fine */ DAG_scene_relations_update(G.main, t->scene); -#ifdef WITH_LEGACY_DEPSGRAPH DAG_scene_flush_update(G.main, t->scene, -1, 0); -#endif /* and we store them temporal in base (only used for transform code) */ /* this because after doing updates, the object->recalc is cleared */ @@ -5792,27 +5972,23 @@ static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t) { SpaceClip *sc = t->sa->spacedata.first; MovieClip *clip = ED_space_clip_get_clip(sc); - MovieTrackingPlaneTrack *plane_track; ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); - int framenr = ED_space_clip_get_clip_frame_number(sc); - - for (plane_track = plane_tracks_base->first; + const int framenr = ED_space_clip_get_clip_frame_number(sc); + /* Update coordinates of modified plane tracks. */ + for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) { bool do_update = false; - if (plane_track->flag & PLANE_TRACK_HIDDEN) { continue; } - do_update |= PLANE_TRACK_VIEW_SELECTED(plane_track) != 0; if (do_update == false) { if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { int i; for (i = 0; i < plane_track->point_tracksnr; i++) { MovieTrackingTrack *track = plane_track->point_tracks[i]; - if (TRACK_VIEW_SELECTED(sc, track)) { do_update = true; break; @@ -5820,15 +5996,14 @@ static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t) } } } - if (do_update) { BKE_tracking_track_plane_from_existing_motion(plane_track, framenr); } } - - if (t->scene->nodetree) { - /* tracks can be used for stabilization nodes, - * flush update for such nodes */ + if (t->scene->nodetree != NULL) { + /* Tracks can be used for stabilization nodes, + * flush update for such nodes. + */ nodeUpdateID(t->scene->nodetree, &clip->id); WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL); } @@ -7656,7 +7831,7 @@ static void createTransGPencil(bContext *C, TransInfo *t) float mtx[3][3], smtx[3][3]; const Scene *scene = CTX_data_scene(C); - const int cfra = CFRA; + const int cfra_scene = CFRA; const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0; @@ -7681,7 +7856,7 @@ static void createTransGPencil(bContext *C, TransInfo *t) if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { bGPDframe *gpf = gpl->actframe; bGPDstroke *gps; - + for (gps = gpf->strokes.first; gps; gps = gps->next) { /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) { @@ -7737,6 +7912,7 @@ static void createTransGPencil(bContext *C, TransInfo *t) for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* only editable and visible layers are considered */ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { + const int cfra = (gpl->flag & GP_LAYER_FRAMELOCK) ? gpl->actframe->framenum : cfra_scene; bGPDframe *gpf = gpl->actframe; bGPDstroke *gps; float diff_mat[4][4]; @@ -7753,7 +7929,6 @@ static void createTransGPencil(bContext *C, TransInfo *t) * - This is useful when animating as it saves that "uh-oh" moment when you realize you've * spent too much time editing the wrong frame... */ - // XXX: should this be allowed when framelock is enabled? if (gpf->framenum != cfra) { gpf = BKE_gpencil_frame_addcopy(gpl, cfra); /* in some weird situations (framelock enabled) return NULL */ @@ -8033,7 +8208,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 { |