From bb158ad5721b98086b77a8168a53c4901540907d Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 12 Jul 2009 03:42:39 +0000 Subject: 2.5 - Editing Animation data (keyframes/nla-strips) using transform tools now refreshes the 3d-view in realtime. For now, this directly sets the update flags, though this really should be calling the Depsgraph API instead. --- source/blender/editors/space_view3d/space_view3d.c | 12 ++ source/blender/editors/transform/transform.c | 2 +- source/blender/editors/transform/transform.h | 2 + .../editors/transform/transform_conversions.c | 225 +++++++++++---------- .../blender/editors/transform/transform_generics.c | 147 ++++++++++---- 5 files changed, 231 insertions(+), 157 deletions(-) diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index f0c3a2c200c..387468f7160 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -413,11 +413,13 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) switch(wmn->data) { case ND_KEYFRAME_EDIT: case ND_KEYFRAME_PROP: + case ND_NLA_EDIT: case ND_NLA_ACTCHANGE: case ND_ANIMCHAN_SELECT: ED_region_tag_redraw(ar); break; } + break; case NC_SCENE: switch(wmn->data) { case ND_TRANSFORM: @@ -536,6 +538,16 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch(wmn->category) { + case NC_ANIMATION: + switch(wmn->data) { + case ND_KEYFRAME_EDIT: + case ND_KEYFRAME_PROP: + case ND_NLA_EDIT: + case ND_NLA_ACTCHANGE: + ED_region_tag_redraw(ar); + break; + } + break; case NC_SCENE: switch(wmn->data) { case ND_FRAME: diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 888a15e2534..d45a6f42232 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -308,7 +308,7 @@ static void viewRedrawForce(bContext *C, TransInfo *t) WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); } else if (t->spacetype == SPACE_NLA) { - WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL); } else if(t->spacetype == SPACE_NODE) { diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 00353cfc457..db78632e76a 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -163,6 +163,8 @@ typedef struct TransDataSeq { /* for NLA transform (stored in td->extra pointer) */ typedef struct TransDataNla { + ID *id; /* ID-block NLA-data is attached to */ + struct NlaTrack *oldTrack; /* Original NLA-Track that the strip belongs to */ struct NlaTrack *nlt; /* Current NLA-Track that the strip belongs to */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 2262c6cdeaa..3d643a2dec1 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2578,28 +2578,28 @@ static void createTransNlaData(bContext *C, TransInfo *t) Scene *scene= CTX_data_scene(C); TransData *td = NULL; TransDataNla *tdn = NULL; - + bAnimContext ac; ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; - + int count=0; char side; - + /* determine what type of data we are operating on */ if (ANIM_animdata_get_context(C, &ac) == 0) return; - + /* filter data */ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - + /* which side of the current frame should be allowed */ if (t->mode == TFM_TIME_EXTEND) { /* only side on which mouse is gets transformed */ float xmouse, ymouse; - + UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse); side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side } @@ -2607,15 +2607,15 @@ static void createTransNlaData(bContext *C, TransInfo *t) /* normal transform - both sides of current frame are considered */ side = 'B'; } - + /* loop 1: count how many strips are selected (consider each strip as 2 points) */ for (ale= anim_data.first; ale; ale= ale->next) { NlaTrack *nlt= (NlaTrack *)ale->data; NlaStrip *strip; - + /* make some meta-strips for chains of selected strips */ BKE_nlastrips_make_metas(&nlt->strips, 1); - + /* only consider selected strips */ for (strip= nlt->strips.first; strip; strip= strip->next) { // TODO: we can make strips have handles later on... @@ -2628,29 +2628,29 @@ static void createTransNlaData(bContext *C, TransInfo *t) } } } - + /* stop if trying to build list if nothing selected */ if (count == 0) { /* cleanup temp list */ BLI_freelistN(&anim_data); return; } - + /* allocate memory for data */ t->total= count; - + t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(NLA Editor)"); td= t->data; t->customData= MEM_callocN(t->total*sizeof(TransDataNla), "TransDataNla (NLA Editor)"); tdn= t->customData; - + /* loop 2: build transdata array */ for (ale= anim_data.first; ale; ale= ale->next) { /* only if a real NLA-track */ if (ale->type == ANIMTYPE_NLATRACK) { NlaTrack *nlt= (NlaTrack *)ale->data; NlaStrip *strip; - + /* only consider selected strips */ for (strip= nlt->strips.first; strip; strip= strip->next) { // TODO: we can make strips have handles later on... @@ -2667,44 +2667,45 @@ static void createTransNlaData(bContext *C, TransInfo *t) * cases, there will need to be 1 of these tdn elements in the array skipped... */ float center[3], yval; - + /* firstly, init tdn settings */ + tdn->id= ale->id; tdn->oldTrack= tdn->nlt= nlt; tdn->strip= strip; tdn->trackIndex= BLI_findindex(&nlt->strips, strip); - + yval= (float)(tdn->trackIndex * NLACHANNEL_STEP); - + tdn->h1[0]= strip->start; tdn->h1[1]= yval; tdn->h2[0]= strip->end; tdn->h2[1]= yval; - + center[0]= (float)CFRA; center[1]= yval; center[2]= 0.0f; - + /* set td's based on which handles are applicable */ if (FrameOnMouseSide(side, strip->start, (float)CFRA)) { /* just set tdn to assume that it only has one handle for now */ tdn->handle= -1; - + /* now, link the transform data up to this data */ if (t->mode == TFM_TRANSLATION) { td->loc= tdn->h1; VECCOPY(td->iloc, tdn->h1); - + /* store all the other gunk that is required by transform */ VECCOPY(td->center, center); memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; - + td->ext= NULL; td->tdi= NULL; td->val= NULL; - + td->flag |= TD_SELECTED; td->dist= 0.0f; - + Mat3One(td->mtx); Mat3One(td->smtx); } @@ -2712,7 +2713,7 @@ static void createTransNlaData(bContext *C, TransInfo *t) td->val= &tdn->h1[0]; td->ival= tdn->h1[0]; } - + td->extra= tdn; td++; } @@ -2720,22 +2721,22 @@ static void createTransNlaData(bContext *C, TransInfo *t) { /* if tdn is already holding the start handle, then we're doing both, otherwise, only end */ tdn->handle= (tdn->handle) ? 2 : 1; - + /* now, link the transform data up to this data */ if (t->mode == TFM_TRANSLATION) { td->loc= tdn->h2; VECCOPY(td->iloc, tdn->h2); - + /* store all the other gunk that is required by transform */ VECCOPY(td->center, center); memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; - + td->ext= NULL; td->tdi= NULL; td->val= NULL; - + td->flag |= TD_SELECTED; td->dist= 0.0f; - + Mat3One(td->mtx); Mat3One(td->smtx); } @@ -2743,11 +2744,11 @@ static void createTransNlaData(bContext *C, TransInfo *t) td->val= &tdn->h2[0]; td->ival= tdn->h2[0]; } - + td->extra= tdn; td++; } - + /* if both handles were used, skip the next tdn (i.e. leave it blank) since the counting code is dumb... * otherwise, just advance to the next one... */ @@ -3114,32 +3115,32 @@ static void createTransActionData(bContext *C, TransInfo *t) Scene *scene= CTX_data_scene(C); TransData *td = NULL; tGPFtransdata *tfd = NULL; - + bAnimContext ac; ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; - + int count=0; float cfra; char side; - + /* determine what type of data we are operating on */ if (ANIM_animdata_get_context(C, &ac) == 0) return; - + /* filter data */ if (ac.datatype == ANIMCONT_GPENCIL) filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT); else filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - + /* which side of the current frame should be allowed */ if (t->mode == TFM_TIME_EXTEND) { /* only side on which mouse is gets transformed */ float xmouse, ymouse; - + UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse); side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side } @@ -3147,11 +3148,11 @@ static void createTransActionData(bContext *C, TransInfo *t) /* normal transform - both sides of current frame are considered */ side = 'B'; } - + /* loop 1: fully select ipo-keys and count how many BezTriples are selected */ for (ale= anim_data.first; ale; ale= ale->next) { AnimData *adt= ANIM_nla_mapping_get(&ac, ale); - + /* convert current-frame to action-time (slightly less accurate, espcially under * higher scaling ratios, but is faster than converting all points) */ @@ -3159,26 +3160,26 @@ static void createTransActionData(bContext *C, TransInfo *t) cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra = (float)CFRA; - + //if (ale->type == ANIMTYPE_GPLAYER) // count += count_gplayer_frames(ale->data, side, cfra); //else count += count_fcurve_keys(ale->key_data, side, cfra); } - + /* stop if trying to build list if nothing selected */ if (count == 0) { /* cleanup temp list */ BLI_freelistN(&anim_data); return; } - + /* allocate memory for data */ t->total= count; - + t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(Action Editor)"); td= t->data; - + if (ac.datatype == ANIMCONT_GPENCIL) { if (t->mode == TFM_TIME_SLIDE) { t->customData= MEM_callocN((sizeof(float)*2)+(sizeof(tGPFtransdata)*count), "TimeSlide + tGPFtransdata"); @@ -3191,7 +3192,7 @@ static void createTransActionData(bContext *C, TransInfo *t) } else if (t->mode == TFM_TIME_SLIDE) t->customData= MEM_callocN(sizeof(float)*2, "TimeSlide Min/Max"); - + /* loop 2: build transdata array */ for (ale= anim_data.first; ale; ale= ale->next) { //if (ale->type == ANIMTYPE_GPLAYER) { @@ -3205,7 +3206,7 @@ static void createTransActionData(bContext *C, TransInfo *t) //else { AnimData *adt= ANIM_nla_mapping_get(&ac, ale); FCurve *fcu= (FCurve *)ale->key_data; - + /* convert current-frame to action-time (slightly less accurate, espcially under * higher scaling ratios, but is faster than converting all points) */ @@ -3213,22 +3214,22 @@ static void createTransActionData(bContext *C, TransInfo *t) cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra = (float)CFRA; - + td= FCurveToTransData(td, fcu, adt, side, cfra); //} } - + /* check if we're supposed to be setting minx/maxx for TimeSlide */ if (t->mode == TFM_TIME_SLIDE) { float min=999999999.0f, max=-999999999.0f; int i; - + td= (t->data + 1); for (i=1; i < count; i+=3, td+=3) { if (min > *(td->val)) min= *(td->val); if (max < *(td->val)) max= *(td->val); } - + /* minx/maxx values used by TimeSlide are stored as a * calloced 2-float array in t->customData. This gets freed * in postTrans (T_FREE_CUSTOMDATA). @@ -3254,18 +3255,18 @@ static void bezt_to_transdata (TransData *td, TransData2D *td2d, AnimData *adt, * Due to NLA mapping, we apply NLA mapping to some of the verts here, * and then that mapping will be undone after transform is done. */ - + if (adt) { td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_UNMAP); td2d->loc[1] = loc[1]; td2d->loc[2] = 0.0f; td2d->loc2d = loc; - + td->loc = td2d->loc; td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_UNMAP); td->center[1] = cent[1]; td->center[2] = 0.0f; - + VECCOPY(td->iloc, td->loc); } else { @@ -3273,32 +3274,32 @@ static void bezt_to_transdata (TransData *td, TransData2D *td2d, AnimData *adt, td2d->loc[1] = loc[1]; td2d->loc[2] = 0.0f; td2d->loc2d = loc; - + td->loc = td2d->loc; VECCOPY(td->center, cent); VECCOPY(td->iloc, td->loc); } - + memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; - + td->ext= NULL; td->tdi= NULL; td->val= NULL; - + /* store AnimData info in td->extra, for applying mapping when flushing */ td->extra= adt; - + if (selected) { td->flag |= TD_SELECTED; td->dist= 0.0f; } else td->dist= MAXFLOAT; - + if (ishandle) td->flag |= TD_NOTIMESNAP; if (intvals) td->flag |= TD_INTVALUES; - + Mat3One(td->mtx); Mat3One(td->smtx); } @@ -3308,34 +3309,34 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) Scene *scene= CTX_data_scene(C); ARegion *ar= CTX_wm_region(C); View2D *v2d= &ar->v2d; - + TransData *td = NULL; TransData2D *td2d = NULL; - + bAnimContext ac; ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; - + BezTriple *bezt, *prevbezt; int count=0, i; float cfra; char side; - + /* determine what type of data we are operating on */ if (ANIM_animdata_get_context(C, &ac) == 0) return; - + /* filter data */ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_CURVEVISIBLE); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - + /* which side of the current frame should be allowed */ // XXX we still want this mode, but how to get this using standard transform too? if (t->mode == TFM_TIME_EXTEND) { /* only side on which mouse is gets transformed */ float xmouse, ymouse; - + UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse); side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side } @@ -3343,12 +3344,12 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) /* normal transform - both sides of current frame are considered */ side = 'B'; } - + /* loop 1: count how many BezTriples (specifically their verts) are selected (or should be edited) */ for (ale= anim_data.first; ale; ale= ale->next) { AnimData *adt= ANIM_nla_mapping_get(&ac, ale); FCurve *fcu= (FCurve *)ale->key_data; - + /* convert current-frame to action-time (slightly less accurate, espcially under * higher scaling ratios, but is faster than converting all points) */ @@ -3356,7 +3357,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra = (float)CFRA; - + /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse */ if (fcu->bezt) { for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) { @@ -3384,30 +3385,30 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) } } } - + /* stop if trying to build list if nothing selected */ if (count == 0) { /* cleanup temp list */ BLI_freelistN(&anim_data); return; } - + /* allocate memory for data */ t->total= count; - + t->data= MEM_callocN(t->total*sizeof(TransData), "TransData (Graph Editor)"); /* for each 2d vert a 3d vector is allocated, so that they can be treated just as if they were 3d verts */ t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransData2D (Graph Editor)"); - + td= t->data; td2d= t->data2d; - + /* loop 2: build transdata arrays */ for (ale= anim_data.first; ale; ale= ale->next) { AnimData *adt= ANIM_nla_mapping_get(&ac, ale); FCurve *fcu= (FCurve *)ale->key_data; short intvals= (fcu->flag & FCURVE_INT_VALUES); - + /* convert current-frame to action-time (slightly less accurate, espcially under * higher scaling ratios, but is faster than converting all points) */ @@ -3415,16 +3416,16 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); else cfra = (float)CFRA; - + /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */ bezt= fcu->bezt; prevbezt= NULL; - + for (i=0; i < fcu->totvert; i++, prevbezt=bezt, bezt++) { if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { TransDataCurveHandleFlags *hdata = NULL; short h1=1, h2=1; - + /* only include handles if selected, and interpolaton mode uses beztriples */ if ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) { if (bezt->f1 & SELECT) { @@ -3443,7 +3444,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) else h2= 0; } - + /* only include main vert if selected */ if (bezt->f2 & SELECT) { /* if scaling around individuals centers, do no include keyframes */ @@ -3453,10 +3454,10 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) if (hdata == NULL) hdata = initTransDataCurveHandes(td, bezt); } - + bezt_to_transdata(td++, td2d++, adt, bezt->vec[1], bezt->vec[1], 1, 0, intvals); } - + /* special hack (must be done after initTransDataCurveHandes(), as that stores handle settings to restore...): * - Check if we've got entire BezTriple selected and we're scaling/rotating that point, * then check if we're using auto-handles. @@ -3471,11 +3472,11 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) } } } - + /* Sets handles based on the selection */ testhandles_fcurve(fcu); } - + /* cleanup temp list */ BLI_freelistN(&anim_data); } @@ -3502,19 +3503,19 @@ static BeztMap *bezt_to_beztmaps (BezTriple *bezts, int totvert) BezTriple *prevbezt= NULL; BeztMap *bezm, *bezms; int i; - + /* allocate memory for this array */ if (totvert==0 || bezts==NULL) return NULL; bezm= bezms= MEM_callocN(sizeof(BeztMap)*totvert, "BeztMaps"); - + /* assign beztriples to beztmaps */ for (i=0; i < totvert; i++, bezm++, prevbezt=bezt, bezt++) { bezm->bezt= bezt; - + bezm->oldIndex= i; bezm->newIndex= i; - + bezm->pipo= (prevbezt) ? prevbezt->ipo : bezt->ipo; bezm->cipo= bezt->ipo; } @@ -3527,11 +3528,11 @@ static void sort_time_beztmaps (BeztMap *bezms, int totvert) { BeztMap *bezm; int i, ok= 1; - + /* keep repeating the process until nothing is out of place anymore */ while (ok) { ok= 0; - + bezm= bezms; i= totvert; while (i--) { @@ -3540,13 +3541,13 @@ static void sort_time_beztmaps (BeztMap *bezms, int totvert) if (bezm->bezt->vec[1][0] > (bezm+1)->bezt->vec[1][0]) { bezm->newIndex++; (bezm+1)->newIndex--; - + SWAP(BeztMap, *bezm, *(bezm+1)); - + ok= 1; } } - + /* do we need to check if the handles need to be swapped? * optimisation: this only needs to be performed in the first loop */ @@ -3562,7 +3563,7 @@ static void sort_time_beztmaps (BeztMap *bezms, int totvert) bezm->swapHs = -1; } } - + bezm++; } } @@ -3576,13 +3577,13 @@ static void beztmap_to_data (TransInfo *t, FCurve *fcu, BeztMap *bezms, int totv TransData2D *td; int i, j; char *adjusted; - + /* dynamically allocate an array of chars to mark whether an TransData's * pointers have been fixed already, so that we don't override ones that are * already done */ adjusted= MEM_callocN(t->total, "beztmap_adjusted_map"); - + /* for each beztmap item, find if it is used anywhere */ bezm= bezms; for (i= 0; i < totvert; i++, bezm++) { @@ -3593,7 +3594,7 @@ static void beztmap_to_data (TransInfo *t, FCurve *fcu, BeztMap *bezms, int totv for (j= 0; j < t->total; j++, td++) { /* skip item if already marked */ if (adjusted[j] != 0) continue; - + /* only selected verts */ if (bezm->pipo == BEZT_IPO_BEZ) { if (bezm->bezt->f1 & SELECT) { @@ -3624,9 +3625,9 @@ static void beztmap_to_data (TransInfo *t, FCurve *fcu, BeztMap *bezms, int totv } } } - + } - + /* free temp memory used for 'adjusted' array */ MEM_freeN(adjusted); } @@ -3641,25 +3642,25 @@ static void beztmap_to_data (TransInfo *t, FCurve *fcu, BeztMap *bezms, int totv void remake_graph_transdata (TransInfo *t, ListBase *anim_data) { bAnimListElem *ale; - + /* sort and reassign verts */ for (ale= anim_data->first; ale; ale= ale->next) { FCurve *fcu= (FCurve *)ale->key_data; - + if (fcu->bezt) { BeztMap *bezm; - + /* adjust transform-data pointers */ bezm= bezt_to_beztmaps(fcu->bezt, fcu->totvert); sort_time_beztmaps(bezm, fcu->totvert); beztmap_to_data(t, fcu, bezm, fcu->totvert); - + /* free mapping stuff */ MEM_freeN(bezm); - + /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */ sort_time_fcurve(fcu); - + /* make sure handles are all set correctly */ testhandles_fcurve(fcu); } @@ -3677,11 +3678,11 @@ void flushTransGraphData(TransInfo *t) Scene *scene= t->scene; double secf= FPS; int a; - + /* flush to 2d vector from internally used 3d vector */ for (a=0, td= t->data, td2d=t->data2d; atotal; a++, td++, td2d++) { AnimData *adt= (AnimData *)td->extra; /* pointers to relevant AnimData blocks are stored in the td->extra pointers */ - + /* handle snapping for time values * - we should still be in NLA-mapping timespace * - only apply to keyframes (but never to handles) @@ -3694,19 +3695,19 @@ void flushTransGraphData(TransInfo *t) else td2d->loc[0]= (float)( floor(td2d->loc[0]+0.5f) ); break; - + case SACTSNAP_MARKER: /* snap to nearest marker */ td2d->loc[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, td2d->loc[0]); break; } } - - /* we need to unapply the nla-scaling from the time in some situations */ + + /* we need to unapply the nla-mapping from the time in some situations */ if (adt) td2d->loc2d[0]= BKE_nla_tweakedit_remap(adt, td2d->loc[0], NLATIME_CONVERT_UNMAP); else td2d->loc2d[0]= td2d->loc[0]; - + /* if int-values only, truncate to integers */ if (td->flag & TD_INTVALUES) td2d->loc2d[1]= (float)((int)td2d->loc[1]); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index af56079727f..560b37caf0a 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -264,6 +264,29 @@ static void editmesh_apply_to_mirror(TransInfo *t) } } +/* tags the given ID block for refreshes (if applicable) due to + * Animation Editor editing + */ +static void animedit_refresh_id_tags (ID *id) +{ + AnimData *adt= BKE_animdata_from_id(id); + + /* tag AnimData for refresh so that other views will update in realtime with these changes */ + if (adt) + adt->recalc |= ADT_RECALC_ANIM; + + /* if ID-block is Object, set recalc flags */ + // TODO: this should probably go through the depsgraph instead... but for now, let's be lazy + switch (GS(id->name)) { + case ID_OB: + { + Object *ob= (Object *)id; + ob->recalc |= OB_RECALC; + } + break; + } +} + /* called for updating while transform acts, once per redraw */ void recalcData(TransInfo *t) { @@ -281,60 +304,93 @@ void recalcData(TransInfo *t) else if (t->spacetype==SPACE_SEQ) { flushTransSeq(t); } + else if (t->spacetype == SPACE_ACTION) { + SpaceAction *sact= (SpaceAction *)t->sa->spacedata.first; + Scene *scene; + + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* initialise relevant anim-context 'context' data from TransInfo data */ + /* NOTE: sync this with the code in ANIM_animdata_get_context() */ + memset(&ac, 0, sizeof(bAnimContext)); + + scene= ac.scene= t->scene; + ac.obact= OBACT; + ac.sa= t->sa; + ac.ar= t->ar; + ac.spacetype= (t->sa)? t->sa->spacetype : 0; + ac.regiontype= (t->ar)? t->ar->regiontype : 0; + + ANIM_animdata_context_getdata(&ac); + + /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* just tag these animdata-blocks to recalc, assuming that some data there changed */ + for (ale= anim_data.first; ale; ale= ale->next) { + /* set refresh tags for objects using this animation */ + animedit_refresh_id_tags(ale->id); + } + + /* now free temp channels */ + BLI_freelistN(&anim_data); + } else if (t->spacetype == SPACE_IPO) { SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first; Scene *scene; - + ListBase anim_data = {NULL, NULL}; bAnimContext ac; int filter; - + bAnimListElem *ale; int dosort = 0; - - + + /* initialise relevant anim-context 'context' data from TransInfo data */ /* NOTE: sync this with the code in ANIM_animdata_get_context() */ memset(&ac, 0, sizeof(bAnimContext)); - + scene= ac.scene= t->scene; ac.obact= OBACT; ac.sa= t->sa; ac.ar= t->ar; ac.spacetype= (t->sa)? t->sa->spacetype : 0; ac.regiontype= (t->ar)? t->ar->regiontype : 0; - + ANIM_animdata_context_getdata(&ac); - + /* do the flush first */ flushTransGraphData(t); - + /* get curves to check if a re-sort is needed */ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY | ANIMFILTER_CURVEVISIBLE); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - + /* now test if there is a need to re-sort */ for (ale= anim_data.first; ale; ale= ale->next) { FCurve *fcu= (FCurve *)ale->key_data; - + AnimData *adt= BKE_animdata_from_id(ale->id); + /* watch it: if the time is wrong: do not correct handles yet */ if (test_time_fcurve(fcu)) dosort++; else calchandles_fcurve(fcu); + + /* set refresh tags for objects using this animation */ + animedit_refresh_id_tags(ale->id); } - + /* do resort and other updates? */ if (dosort) remake_graph_transdata(t, &anim_data); - //if (sipo->showkey) update_ipokey_val(); - + /* now free temp channels */ BLI_freelistN(&anim_data); - - /* update realtime - not working? */ - if (sipo->lock) { - - } } else if (t->spacetype == SPACE_NLA) { TransDataNla *tdn= (TransDataNla *)t->customData; @@ -342,7 +398,7 @@ void recalcData(TransInfo *t) Scene *scene= t->scene; double secf= FPS; int i; - + /* for each strip we've got, perform some additional validation of the values that got set before * using RNA to set the value (which does some special operations when setting these values to make * sure that everything works ok) @@ -352,42 +408,45 @@ void recalcData(TransInfo *t) PointerRNA strip_ptr; short pExceeded, nExceeded, iter; int delta_y1, delta_y2; - + /* if this tdn has no handles, that means it is just a dummy that should be skipped */ if (tdn->handle == 0) continue; - + + /* set refresh tags for objects using this animation */ + animedit_refresh_id_tags(tdn->id); + /* if cancelling transform, just write the values without validating, then move on */ if (t->state == TRANS_CANCEL) { /* clear the values by directly overwriting the originals, but also need to restore * endpoints of neighboring transition-strips */ - + /* start */ strip->start= tdn->h1[0]; - + if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) strip->prev->end= tdn->h1[0]; - + /* end */ strip->end= tdn->h2[0]; - + if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION)) strip->next->start= tdn->h2[0]; - + /* flush transforms to child strips (since this should be a meta) */ BKE_nlameta_flush_transforms(strip); - + /* restore to original track (if needed) */ if (tdn->oldTrack != tdn->nlt) { /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */ BLI_remlink(&tdn->nlt->strips, strip); BLI_addtail(&tdn->oldTrack->strips, strip); } - + continue; } - + /* firstly, check if the proposed transform locations would overlap with any neighbouring strips * (barring transitions) which are absolute barriers since they are not being moved * @@ -396,7 +455,7 @@ void recalcData(TransInfo *t) for (iter=0; iter < 5; iter++) { pExceeded= ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h1[0] < strip->prev->end)); nExceeded= ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h2[0] > strip->next->start)); - + if ((pExceeded && nExceeded) || (iter == 4) ) { /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise) * - simply crop strip to fit within the bounds of the strips bounding it @@ -414,21 +473,21 @@ void recalcData(TransInfo *t) else if (nExceeded) { /* move backwards */ float offset= tdn->h2[0] - strip->next->start; - + tdn->h1[0] -= offset; tdn->h2[0] -= offset; } else if (pExceeded) { /* more forwards */ float offset= strip->prev->end - tdn->h1[0]; - + tdn->h1[0] += offset; tdn->h2[0] += offset; } else /* all is fine and well */ break; } - + /* handle auto-snapping */ switch (snla->autosnap) { case SACTSNAP_FRAME: /* snap to nearest frame/time */ @@ -441,35 +500,35 @@ void recalcData(TransInfo *t) tdn->h2[0]= (float)( floor(tdn->h2[0]+0.5f) ); } break; - + case SACTSNAP_MARKER: /* snap to nearest marker */ tdn->h1[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]); tdn->h2[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]); break; } - + /* use RNA to write the values... */ // TODO: do we need to write in 2 passes to make sure that no truncation goes on? RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); - + RNA_float_set(&strip_ptr, "start_frame", tdn->h1[0]); RNA_float_set(&strip_ptr, "end_frame", tdn->h2[0]); - + /* flush transforms to child strips (since this should be a meta) */ BKE_nlameta_flush_transforms(strip); - - + + /* now, check if we need to try and move track * - we need to calculate both, as only one may have been altered by transform if only 1 handle moved */ delta_y1= ((int)tdn->h1[1] / NLACHANNEL_STEP - tdn->trackIndex); delta_y2= ((int)tdn->h2[1] / NLACHANNEL_STEP - tdn->trackIndex); - + if (delta_y1 || delta_y2) { NlaTrack *track; int delta = (delta_y2) ? delta_y2 : delta_y1; int n; - + /* move in the requested direction, checking at each layer if there's space for strip to pass through, * stopping on the last track available or that we're able to fit in */ @@ -480,7 +539,7 @@ void recalcData(TransInfo *t) /* move strip to this track */ BLI_remlink(&tdn->nlt->strips, strip); BKE_nlatrack_add_strip(track, strip); - + tdn->nlt= track; tdn->trackIndex += (n + 1); /* + 1, since n==0 would mean that we didn't change track */ } @@ -491,14 +550,14 @@ void recalcData(TransInfo *t) else { /* make delta 'positive' before using it, since we now know to go backwards */ delta= -delta; - + for (track=tdn->nlt->prev, n=0; (track) && (n < delta); track=track->prev, n++) { /* check if space in this track for the strip */ if (BKE_nlatrack_has_space(track, strip->start, strip->end)) { /* move strip to this track */ BLI_remlink(&tdn->nlt->strips, strip); BKE_nlatrack_add_strip(track, strip); - + tdn->nlt= track; tdn->trackIndex -= (n - 1); /* - 1, since n==0 would mean that we didn't change track */ } -- cgit v1.2.3