2.5 - Fixes for animating enum values
authorJoshua Leung <aligorith@gmail.com>
Thu, 28 May 2009 01:57:29 +0000 (01:57 +0000)
committerJoshua Leung <aligorith@gmail.com>
Thu, 28 May 2009 01:57:29 +0000 (01:57 +0000)
Interpolation between keyframes for enum values (and booleans) can only be constant now.

TODO:
A way to do this for modifiers is still needed.

source/blender/blenkernel/intern/fcurve.c
source/blender/blenkernel/intern/ipo.c
source/blender/editors/animation/keyframing.c
source/blender/editors/space_graph/graph_draw.c
source/blender/makesdna/DNA_anim_types.h

index fed5ffc2ebdb7ced01104bebe58b14870f92785b..ad8115ba9aaf487c62b6ce884df2558944bdfaeb 100644 (file)
@@ -164,7 +164,7 @@ FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array
        /* check paths of curves, then array indices... */
        for (fcu= list->first; fcu; fcu= fcu->next) {
                /* simple string-compare (this assumes that they have the same root...) */
-               if (strcmp(fcu->rna_path, rna_path) == 0) {
+               if (fcu->rna_path && !strcmp(fcu->rna_path, rna_path)) {
                        /* now check indicies */
                        if (fcu->array_index == array_index)
                                return fcu;
@@ -1048,17 +1048,22 @@ static float fcurve_eval_keyframes (FCurve *fcu, BezTriple *bezts, float evaltim
        lastbezt= prevbezt + a;
        
        /* evaluation time at or past endpoints? */
-       if (prevbezt->vec[1][0] >= evaltime) {
+       if (prevbezt->vec[1][0] >= evaltime) 
+       {
                /* before or on first keyframe */
-               if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (prevbezt->ipo != BEZT_IPO_CONST)) {
+               if ( (fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (prevbezt->ipo != BEZT_IPO_CONST) &&
+                       !(fcu->flag & FCURVE_DISCRETE_VALUES) ) 
+               {
                        /* linear or bezier interpolation */
-                       if (prevbezt->ipo==BEZT_IPO_LIN) {
+                       if (prevbezt->ipo==BEZT_IPO_LIN) 
+                       {
                                /* Use the next center point instead of our own handle for
                                 * linear interpolated extrapolate 
                                 */
                                if (fcu->totvert == 1) 
                                        cvalue= prevbezt->vec[1][1];
-                               else {
+                               else 
+                               {
                                        bezt = prevbezt+1;
                                        dx= prevbezt->vec[1][0] - evaltime;
                                        fac= bezt->vec[1][0] - prevbezt->vec[1][0];
@@ -1072,7 +1077,8 @@ static float fcurve_eval_keyframes (FCurve *fcu, BezTriple *bezts, float evaltim
                                                cvalue= prevbezt->vec[1][1];
                                }
                        } 
-                       else {
+                       else 
+                       {
                                /* Use the first handle (earlier) of first BezTriple to calculate the
                                 * gradient and thus the value of the curve at evaltime
                                 */
@@ -1088,24 +1094,30 @@ static float fcurve_eval_keyframes (FCurve *fcu, BezTriple *bezts, float evaltim
                                        cvalue= prevbezt->vec[1][1];
                        }
                }
-               else {
+               else 
+               {
                        /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, 
                         * so just extend first keyframe's value 
                         */
                        cvalue= prevbezt->vec[1][1];
                }
        }
-       else if (lastbezt->vec[1][0] <= evaltime) {
+       else if (lastbezt->vec[1][0] <= evaltime) 
+       {
                /* after or on last keyframe */
-               if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (lastbezt->ipo != BEZT_IPO_CONST)) {
+               if ( (fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (lastbezt->ipo != BEZT_IPO_CONST) &&
+                       !(fcu->flag & FCURVE_DISCRETE_VALUES) ) 
+               {
                        /* linear or bezier interpolation */
-                       if (lastbezt->ipo==BEZT_IPO_LIN) {
+                       if (lastbezt->ipo==BEZT_IPO_LIN) 
+                       {
                                /* Use the next center point instead of our own handle for
                                 * linear interpolated extrapolate 
                                 */
                                if (fcu->totvert == 1) 
                                        cvalue= lastbezt->vec[1][1];
-                               else {
+                               else 
+                               {
                                        prevbezt = lastbezt - 1;
                                        dx= evaltime - lastbezt->vec[1][0];
                                        fac= lastbezt->vec[1][0] - prevbezt->vec[1][0];
@@ -1119,7 +1131,8 @@ static float fcurve_eval_keyframes (FCurve *fcu, BezTriple *bezts, float evaltim
                                                cvalue= lastbezt->vec[1][1];
                                }
                        } 
-                       else {
+                       else 
+                       {
                                /* Use the gradient of the second handle (later) of last BezTriple to calculate the
                                 * gradient and thus the value of the curve at evaltime
                                 */
@@ -1135,24 +1148,30 @@ static float fcurve_eval_keyframes (FCurve *fcu, BezTriple *bezts, float evaltim
                                        cvalue= lastbezt->vec[1][1];
                        }
                }
-               else {
+               else 
+               {
                        /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, 
                         * so just extend last keyframe's value 
                         */
                        cvalue= lastbezt->vec[1][1];
                }
        }
-       else {
+       else 
+       {
                /* evaltime occurs somewhere in the middle of the curve */
-               for (a=0; prevbezt && bezt && (a < fcu->totvert-1); a++, prevbezt=bezt, bezt++) {  
+               for (a=0; prevbezt && bezt && (a < fcu->totvert-1); a++, prevbezt=bezt, bezt++) 
+               {  
                        /* evaltime occurs within the interval defined by these two keyframes */
-                       if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime)) {
+                       if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime)) 
+                       {
                                /* value depends on interpolation mode */
-                               if (prevbezt->ipo == BEZT_IPO_CONST) {
+                               if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES))
+                               {
                                        /* constant (evaltime not relevant, so no interpolation needed) */
                                        cvalue= prevbezt->vec[1][1];
                                }
-                               else if (prevbezt->ipo == BEZT_IPO_LIN) {
+                               else if (prevbezt->ipo == BEZT_IPO_LIN) 
+                               {
                                        /* linear - interpolate between values of the two keyframes */
                                        fac= bezt->vec[1][0] - prevbezt->vec[1][0];
                                        
@@ -1164,7 +1183,8 @@ static float fcurve_eval_keyframes (FCurve *fcu, BezTriple *bezts, float evaltim
                                        else
                                                cvalue= prevbezt->vec[1][1];
                                }
-                               else {
+                               else 
+                               {
                                        /* bezier interpolation */
                                                /* v1,v2 are the first keyframe and its 2nd handle */
                                        v1[0]= prevbezt->vec[1][0];
index 6a01311f6fc28795a2e6a3466e952ef200f895ad..9c5560be8f3bf7255bd8bcc514dad26e80c467f0 100644 (file)
@@ -1169,7 +1169,7 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
                if (G.f & G_DEBUG) printf("\tconvert bitflag ipocurve, totbits = %d \n", totbits);
                
                /* add the 'only int values' flag */
-               fcu->flag |= FCURVE_INT_VALUES;         
+               fcu->flag |= (FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES);                
                
                /* for each bit we have to remap + check for:
                 * 1) we need to make copy the existing F-Curve data (fcu -> fcurve),
index 9a40fb44f475fd785aa25b1342ae58863abe92b9..4a5f9efa9689fd3f091e8ac4e35e5b8718c3ab02 100644 (file)
@@ -728,8 +728,23 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_
                float curval= 0.0f;
                
                /* set additional flags for the F-Curve (i.e. only integer values) */
-               if (RNA_property_type(prop) != PROP_FLOAT)
-                       fcu->flag |= FCURVE_INT_VALUES;
+               fcu->flag &= ~(FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES);
+               switch (RNA_property_type(prop)) {
+                       case PROP_FLOAT:
+                               /* do nothing */
+                               break;
+                       case PROP_INT:
+                               /* do integer (only 'whole' numbers) interpolation between all points */
+                               fcu->flag |= FCURVE_INT_VALUES;
+                               break;
+                       default:
+                               /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate
+                                * values at all) interpolation between all points
+                                *      - however, we must also ensure that evaluated values are only integers still
+                                */
+                               fcu->flag |= (FCURVE_DISCRETE_VALUES|FCURVE_INT_VALUES);
+                               break;
+               }
                
                /* apply special time tweaking */
                        // XXX check on this stuff...
index f6d9406e7da13aedc921f1e4a9acd2cd4fc43aa9..acf712d0147143a328184f90021bc0780fd1234a 100644 (file)
@@ -748,7 +748,7 @@ void graph_draw_ghost_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, Vie
        FCurve *fcu;
        
        /* draw with thick dotted lines */
-       setlinestyle(1);
+       setlinestyle(10);
        glLineWidth(3.0f);
        
        /* anti-aliased lines for less jagged appearance */
index f30cd63242a78c385f9bc35b8e1a0935e389f286..bf6b9bed5a10815e1355d49d6a676e551891fe85 100644 (file)
@@ -321,8 +321,10 @@ enum {
        
                /* skip evaluation, as RNA-path cannot be resolved (similar to muting, but cannot be set by user) */
        FCURVE_DISABLED                 = (1<<10),
-               /* curve can only have whole-number values (int or boolean types) */
+               /* curve can only have whole-number values (integer types) */
        FCURVE_INT_VALUES               = (1<<11),
+               /* curve can only have certain discrete-number values (no interpolation at all, for enums/booleans) */
+       FCURVE_DISCRETE_VALUES  = (1<<12),
 } eFCurve_Flags;
 
 /* extrapolation modes (only simple value 'extending') */