keyframe transform, both through dopesheet/action editor and graph editor, works...
authorJoseph Eagar <joeedh@gmail.com>
Thu, 6 May 2010 19:54:43 +0000 (19:54 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Thu, 6 May 2010 19:54:43 +0000 (19:54 +0000)
source/blender/editors/interface/interface_draw.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c

index aa111bffaa9801e9fecc7014c27d06dbaacc7b50..74324a244defb73618d1c1f2afaf04767950fe4f 100644 (file)
@@ -1088,8 +1088,12 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti
 
        glTranslatef(centerx, centery, 0.f);
        glScalef(diam, diam, 0.f);
-       glVertexPointer(2, GL_FLOAT, 0, scopes->vecscope);
-       glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+
+       /*apparently this can sometimes be NULL? - joeedh*/
+       if (scopes) {
+               glVertexPointer(2, GL_FLOAT, 0, scopes->vecscope);
+               glDrawArrays(GL_POINTS, 0, scopes->waveform_tot);
+       }
 
        glDisableClientState(GL_VERTEX_ARRAY);
        glPopMatrix();
index 7c98ca44fba1550bea049748b5f78db6047916cd..7f0bc6627d269809c0611e6889ceb3a9070ea6ea 100644 (file)
@@ -202,17 +202,32 @@ void projectIntView(TransInfo *t, float *vec, int *adr)
 
                UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr+1);
        }
-       else if(ELEM3(t->spacetype, SPACE_IPO, SPACE_NLA, SPACE_ACTION)) {
+       else if(t->spacetype == SPACE_ACTION) {
+               SpaceAction *sact = t->sa->spacedata.first;
                int out[2] = {0, 0};
 
-               UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], out, out+1);
+               if (sact->flag & SACTION_DRAWTIME) {
+                       //vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.frs_sec_base));
+
+                       UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], out, out+1);
+               } else {
+                       UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], out, out+1);
+               }
+
+               adr[0]= out[0];
+               adr[1]= out[1];
+       }
+       else if(ELEM(t->spacetype, SPACE_IPO, SPACE_NLA)) {
+               int out[2] = {0, 0};
+
+               UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], out, out+1);
                adr[0]= out[0];
                adr[1]= out[1];
        }
        else if(t->spacetype==SPACE_SEQ) { /* XXX not tested yet, but should work */
                int out[2] = {0, 0};
 
-               UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], out, out+1);
+               UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], out, out+1);
                adr[0]= out[0];
                adr[1]= out[1];
        }
@@ -5285,12 +5300,12 @@ static short getAnimEdit_DrawTime(TransInfo *t)
 /* This function is used by Animation Editor specific transform functions to do
  * the Snap Keyframe to Nearest Frame/Marker
  */
-static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, AnimData *adt, short autosnap)
+static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d, AnimData *adt, short autosnap)
 {
        /* snap key to nearest frame? */
        if (autosnap == SACTSNAP_FRAME) {
                const Scene *scene= t->scene;
-               const short doTime= getAnimEdit_DrawTime(t);
+               const short doTime= 0; //XXX doesn't work - getAnimEdit_DrawTime(t);
                const double secf= FPS;
                double val;
 
@@ -5332,6 +5347,14 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, AnimData *adt, sho
                else
                        *(td->val)= val;
        }
+
+       if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
+               td2d->h1[0] = td2d->ih1[0] + *td->val - td->ival;
+       }
+
+       if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
+               td2d->h2[0] = td2d->ih2[0] + *td->val - td->ival;
+       }
 }
 
 /* ----------------- Translation ----------------------- */
@@ -5394,6 +5417,7 @@ static void headerTimeTranslate(TransInfo *t, char *str)
 static void applyTimeTranslate(TransInfo *t, float sval)
 {
        TransData *td = t->data;
+       TransData2D *td2d = t->data2d;
        Scene *scene = t->scene;
        int i;
 
@@ -5402,16 +5426,18 @@ static void applyTimeTranslate(TransInfo *t, float sval)
 
        const short autosnap= getAnimEdit_SnapMode(t);
 
-       float deltax, val;
+       float deltax, val, valprev;
 
        /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */
-       for (i = 0 ; i < t->total; i++, td++) {
+       for (i = 0 ; i < t->total; i++, td++, td2d++) {
                /* it is assumed that td->extra is a pointer to the AnimData,
                 * whose active action is where this keyframe comes from
                 * (this is only valid when not in NLA)
                 */
                AnimData *adt= (t->spacetype != SPACE_NLA) ? td->extra : NULL;
 
+               valprev = *td->val;
+
                /* check if any need to apply nla-mapping */
                if (adt && t->spacetype != SPACE_SEQ) {
                        deltax = t->values[0];
@@ -5441,7 +5467,7 @@ static void applyTimeTranslate(TransInfo *t, float sval)
                }
 
                /* apply nearest snapping */
-               doAnimEdit_SnapFrame(t, td, adt, autosnap);
+               doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
        }
 }
 
@@ -5652,6 +5678,7 @@ static void headerTimeScale(TransInfo *t, char *str) {
 static void applyTimeScale(TransInfo *t) {
        Scene *scene = t->scene;
        TransData *td = t->data;
+       TransData2D *td2d = t->data2d;
        int i;
 
        const short autosnap= getAnimEdit_SnapMode(t);
@@ -5659,7 +5686,7 @@ static void applyTimeScale(TransInfo *t) {
        const double secf= FPS;
 
 
-       for (i = 0 ; i < t->total; i++, td++) {
+       for (i = 0 ; i < t->total; i++, td++, td2d++) {
                /* it is assumed that td->extra is a pointer to the AnimData,
                 * whose active action is where this keyframe comes from
                 * (this is only valid when not in NLA)
@@ -5685,7 +5712,7 @@ static void applyTimeScale(TransInfo *t) {
                *(td->val) += startx;
 
                /* apply nearest snapping */
-               doAnimEdit_SnapFrame(t, td, adt, autosnap);
+               doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap);
        }
 }
 
index ef13634a6ae6edaedf854a7fe46b6e51d288e347..c1e62eb563c9d3848accebb3092ace39ed9b3c32 100644 (file)
@@ -151,6 +151,9 @@ typedef struct TransDataExtension {
 typedef struct TransData2D {
        float loc[3];           /* Location of data used to transform (x,y,0) */
        float *loc2d;           /* Pointer to real 2d location of data */
+
+       float *h1, *h2;     /* Pointer to handle locations, if handles aren't being moved independantly*/
+       float ih1[2], ih2[2];
 } TransData2D;
 
 /* we need to store 2 handles for each transdata incase the other handle wasnt selected */
@@ -427,6 +430,8 @@ typedef struct TransInfo {
 #define TD_NOTIMESNAP          (1 << 14)       /* for Graph Editor autosnap, indicates that point should not undergo autosnapping */
 #define TD_INTVALUES           (1 << 15)       /* for Graph Editor - curves that can only have int-values need their keyframes tagged with this */
 #define TD_MIRROR_EDGE         (1 << 16)       /* For editmode mirror, clamp to x = 0 */
+#define TD_MOVEHANDLE1         (1 << 17)       /* For fcurve handles, move them along with their keyframes */
+#define TD_MOVEHANDLE2         (1 << 18)
 
 /* transsnap->status */
 #define SNAP_FORCED            1
index 0e11058a24464d0788ce7299aac42f1083043593..3f9b6df07185c26ce085d6541e9a03dd5122661d 100644 (file)
@@ -2972,9 +2972,8 @@ static int count_fcurve_keys(FCurve *fcu, char side, float cfra)
                        bezt->f1 |= SELECT;
                        bezt->f3 |= SELECT;
 
-                       /* increment by 3, as there are 3 points (3 * x-coordinates) that need transform */
                        if (FrameOnMouseSide(side, bezt->vec[1][0], cfra))
-                               count += 3;
+                               count += 1;
                }
        }
 
@@ -3023,9 +3022,10 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt)
  * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
  * on the named side are used.
  */
-static TransData *FCurveToTransData(TransData *td, FCurve *fcu, AnimData *adt, char side, float cfra)
+static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra)
 {
        BezTriple *bezt;
+       TransData2D *td2d = *td2dv;
        int i;
 
        if (fcu == NULL)
@@ -3036,19 +3036,24 @@ static TransData *FCurveToTransData(TransData *td, FCurve *fcu, AnimData *adt, c
                if (BEZSELECTED(bezt)) {
                        /* only add if on the right 'side' of the current frame */
                        if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
-                               /* each control point needs to be added separetely */
-                               TimeToTransData(td, bezt->vec[0], adt);
-                               td++;
-
                                TimeToTransData(td, bezt->vec[1], adt);
-                               td++;
 
-                               TimeToTransData(td, bezt->vec[2], adt);
+                               /*set flags to move handles as necassary*/
+                               td->flag |= TD_MOVEHANDLE1|TD_MOVEHANDLE2;
+                               td2d->h1 = bezt->vec[0];
+                               td2d->h2 = bezt->vec[2];
+
+                               VECCOPY2D(td2d->ih1, td2d->h1);
+                               VECCOPY2D(td2d->ih2, td2d->h2);
+
                                td++;
+                               td2d++;
                        }
                }
        }
 
+       *td2dv = td2d;
+
        return td;
 }
 
@@ -3116,6 +3121,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
 {
        Scene *scene= t->scene;
        TransData *td = NULL;
+       TransData2D *td2d = NULL;
        tGPFtransdata *tfd = NULL;
        
        bAnimContext ac;
@@ -3179,7 +3185,9 @@ static void createTransActionData(bContext *C, TransInfo *t)
        t->total= count;
        
        t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(Action Editor)");
+       t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "transdata2d");
        td= t->data;
+       td2d = t->data2d;
        
        if (ac.datatype == ANIMCONT_GPENCIL) {
                if (t->mode == TFM_TIME_SLIDE) {
@@ -3216,7 +3224,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
                        else
                                cfra = (float)CFRA;
                        
-                       td= FCurveToTransData(td, fcu, adt, t->frame_side, cfra);
+                       td= ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra);
                //}
        }
        
@@ -3248,8 +3256,11 @@ static void createTransActionData(bContext *C, TransInfo *t)
 /* Helper function for createTransGraphEditData, which is reponsible for associating
  * source data with transform data
  */
-static void bezt_to_transdata (TransData *td, TransData2D *td2d, AnimData *adt, float *loc, float *cent, short selected, short ishandle, short intvals)
+static void bezt_to_transdata (TransData *td, TransData2D *td2d, AnimData *adt, BezTriple *bezt, int bi, short selected, short ishandle, short intvals)
 {
+       float *loc = bezt->vec[bi];
+       float *cent = bezt->vec[1];
+
        /* New location from td gets dumped onto the old-location of td2d, which then
         * gets copied to the actual data at td2d->loc2d (bezt->vec[n])
         *
@@ -3280,7 +3291,17 @@ static void bezt_to_transdata (TransData *td, TransData2D *td2d, AnimData *adt,
                VECCOPY(td->center, cent);
                VECCOPY(td->iloc, td->loc);
        }
-       
+
+       if (td->flag & TD_MOVEHANDLE1) {
+               td2d->h1 = bezt->vec[0];
+               VECCOPY2D(td2d->ih1, td2d->h1);
+       } else td2d->h1 = NULL;
+
+       if (td->flag & TD_MOVEHANDLE2) {
+               td2d->h2 = bezt->vec[2];
+               VECCOPY2D(td2d->ih2, td2d->h2);
+       } else td2d->h2 = NULL;
+
        memset(td->axismtx, 0, sizeof(td->axismtx));
        td->axismtx[2][2] = 1.0f;
        
@@ -3300,7 +3321,7 @@ static void bezt_to_transdata (TransData *td, TransData2D *td2d, AnimData *adt,
                td->flag |= TD_NOTIMESNAP;
        if (intvals)
                td->flag |= TD_INTVALUES;
-       
+
        unit_m3(td->mtx);
        unit_m3(td->smtx);
 }
@@ -3362,11 +3383,11 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
                /* F-Curve may not have any keyframes */
                if (fcu->bezt == NULL)
                        continue;
-               
+
                /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse */
                for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
                        if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
-                               if (sipo->around == V3D_LOCAL) {
+                               if (sipo->around == V3D_LOCAL && !ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE)) {
                                        /* for local-pivot we only need to count the number of selected handles only, so that centerpoints don't
                                         * don't get moved wrong
                                         */
@@ -3376,7 +3397,15 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
                                        }
                                        else if (bezt->f2 & SELECT) count++; // TODO: could this cause problems?
                                }
-                               else {
+                               else if (ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)) {
+                                       /* for 'normal' pivots - just include anything that is selected.
+                                          this works a bit differently in translation modes */
+                                       if (bezt->f2 & SELECT) count++;
+                                       else {
+                                               if (bezt->f1 & SELECT) count++;
+                                               if (bezt->f3 & SELECT) count++;
+                                       }
+                               } else {
                                        /* for 'normal' pivots - just include anything that is selected */
                                        if (bezt->f1 & SELECT) count++;
                                        if (bezt->f2 & SELECT) count++;
@@ -3429,23 +3458,32 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
                                TransDataCurveHandleFlags *hdata = NULL;
                                short h1=1, h2=1;
                                
-                               /* only include handles if selected, irrespective of the interpolation modes */
-                               if (bezt->f1 & SELECT) {
-                                       hdata = initTransDataCurveHandles(td, bezt);
-                                       bezt_to_transdata(td++, td2d++, adt, bezt->vec[0], bezt->vec[1], 1, 1, intvals);
-                               }
-                               else
-                                       h1= 0;
-                               if (bezt->f3 & SELECT) {
-                                       if (hdata==NULL)
+                               /* only include handles if selected, irrespective of the interpolation modes.
+                                  also, only treat handles specially if the center point isn't selected. */
+                               if (!ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE) || !(bezt->f2 & SELECT)) {
+                                       if (bezt->f1 & SELECT) {
                                                hdata = initTransDataCurveHandles(td, bezt);
-                                       bezt_to_transdata(td++, td2d++, adt, bezt->vec[2], bezt->vec[1], 1, 1, intvals);
+                                               bezt_to_transdata(td++, td2d++, adt, bezt, 0, 1, 1, intvals);
+                                       } else
+                                               h1= 0;
+
+                                       if (bezt->f3 & SELECT) {
+                                               if (hdata==NULL)
+                                                       hdata = initTransDataCurveHandles(td, bezt);
+                                               bezt_to_transdata(td++, td2d++, adt, bezt, 2, 1, 1, intvals);
+                                       } else
+                                               h2= 0;
                                }
-                               else
-                                       h2= 0;
-                               
-                               /* only include main vert if selected */
+
                                if (bezt->f2 & SELECT) {
+                                        /*move handles relative to center*/
+                                       if (ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)) {
+                                               if (bezt->f1 & SELECT) td->flag |= TD_MOVEHANDLE1;
+                                               if (bezt->f3 & SELECT) td->flag |= TD_MOVEHANDLE2;
+                                       }
+
+                                       /* only include main vert if selected */
+
                                        /* if scaling around individuals centers, do not include keyframes */
                                        if (sipo->around != V3D_LOCAL) {
                                                /* if handles were not selected, store their selection status */
@@ -3454,7 +3492,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
                                                                hdata = initTransDataCurveHandles(td, bezt);
                                                }
                                                
-                                               bezt_to_transdata(td++, td2d++, adt, bezt->vec[1], bezt->vec[1], 1, 0, intvals);
+                                               bezt_to_transdata(td++, td2d++, adt, bezt, 1, 1, 0, intvals);
                                        }
                                        
                                        /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...):
@@ -3700,7 +3738,7 @@ void flushTransGraphData(TransInfo *t)
                                        break;
                        }
                }
-               
+
                /* 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);
@@ -3712,6 +3750,16 @@ void flushTransGraphData(TransInfo *t)
                        td2d->loc2d[1]= (float)((int)td2d->loc[1]);
                else
                        td2d->loc2d[1]= td2d->loc[1];
+
+               if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
+                       td2d->h1[0] = td2d->ih1[0] + td->loc[0] - td->iloc[0];
+                       td2d->h1[1] = td2d->ih1[1] + td->loc[1] - td->iloc[1];
+               }
+
+               if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
+                       td2d->h2[0] = td2d->ih2[0] + td->loc[0] - td->iloc[0];
+                       td2d->h2[1] = td2d->ih2[1] + td->loc[1] - td->iloc[1];
+               }
        }
 }
 
index 59961f5812c97218b5f00f5384c0ae3b9ffb5de3..99793f4010afe85707aead7304f7545c57dfc408 100644 (file)
@@ -1167,6 +1167,7 @@ static void restoreElement(TransData *td) {
        if (td->val) {
                *td->val = td->ival;
        }
+
        if (td->ext && (td->flag&TD_NO_EXT)==0) {
                if (td->ext->rot) {
                        VECCOPY(td->ext->rot, td->ext->irot);
@@ -1188,11 +1189,23 @@ static void restoreElement(TransData *td) {
 void restoreTransObjects(TransInfo *t)
 {
        TransData *td;
-       
+       TransData2D *td2d;
+
        for (td = t->data; td < t->data + t->total; td++) {
                restoreElement(td);
        }
        
+       for (td2d=t->data2d; t->data2d && td2d < t->data2d + t->total; td2d++) {
+               if (td2d->h1) {
+                       td2d->h1[0] = td2d->ih1[0];
+                       td2d->h1[1] = td2d->ih1[1];
+               }
+               if (td2d->h2) {
+                       td2d->h2[0] = td2d->ih2[0];
+                       td2d->h2[1] = td2d->ih2[1];
+               }
+       }
+
        unit_m3(t->mat);
        
        recalcData(t);