Fix T48234: Glitch w/ action constraints sharing an action
authorCampbell Barton <ideasman42@gmail.com>
Fri, 3 Jun 2016 14:54:28 +0000 (00:54 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 3 Jun 2016 14:57:44 +0000 (00:57 +1000)
FCurve evaluation depended on FCurve.curval, which isn't threadsafe.
Now only use this value for debug display,
and pass the value instead of storing in the FCurve for all but debug-display.

source/blender/blenkernel/BKE_animsys.h
source/blender/blenkernel/BKE_fcurve.h
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/fcurve.c
source/blender/editors/space_action/action_edit.c
source/blender/editors/space_graph/graph_edit.c
source/blender/makesdna/DNA_anim_types.h

index dc751747f323d677903e731b4bfa03755b3cdd62..6524afff051e49bd7eb9374d95735dcc0cb5629f 100644 (file)
@@ -177,7 +177,7 @@ void BKE_animsys_evaluate_all_animation(struct Main *main, struct Scene *scene,
 
 /* TODO(sergey): This is mainly a temp public function. */
 struct FCurve;
-bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct AnimMapper *remap, struct FCurve *fcu);
+bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct AnimMapper *remap, struct FCurve *fcu, float curval);
 
 /* ------------ Specialized API --------------- */
 /* There are a few special tools which require these following functions. They are NOT to be used
index 2022d11d5089cdf2288b7a8b3041172e01946ca0..bb4eb652ae26bba7c3d10c1c6730430c9e2e8567 100644 (file)
@@ -279,7 +279,7 @@ void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2]);
 /* evaluate fcurve */
 float evaluate_fcurve(struct FCurve *fcu, float evaltime);
 /* evaluate fcurve and store value */
-void calculate_fcurve(struct FCurve *fcu, float ctime);
+float calculate_fcurve(struct FCurve *fcu, float evaltime);
 
 /* ************* F-Curve Samples API ******************** */
 
index 41950c59a223ab861c8f0df642f5a2e0fe74e7e8..c85a2887a097f519ba5073fbd680c92b4e0245ca 100644 (file)
@@ -1620,7 +1620,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
 }
 
 /* Simple replacement based data-setting of the FCurve using RNA */
-bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu)
+bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu, float curval)
 {
        char *path = NULL;
        bool free_path = false;
@@ -1631,7 +1631,7 @@ bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu)
        
        /* write value to setting */
        if (path)
-               ok = animsys_write_rna_setting(ptr, path, fcu->array_index, fcu->curval);
+               ok = animsys_write_rna_setting(ptr, path, fcu->array_index, curval);
        
        /* free temp path-info */
        if (free_path)
@@ -1654,8 +1654,8 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper
                if ((fcu->grp == NULL) || (fcu->grp->flag & AGRP_MUTED) == 0) {
                        /* check if this curve should be skipped */
                        if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
-                               calculate_fcurve(fcu, ctime);
-                               BKE_animsys_execute_fcurve(ptr, remap, fcu); 
+                               const float curval = calculate_fcurve(fcu, ctime);
+                               BKE_animsys_execute_fcurve(ptr, remap, fcu, curval);
                        }
                }
        }
@@ -1684,8 +1684,8 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime
                                /* evaluate this using values set already in other places
                                 * NOTE: for 'layering' option later on, we should check if we should remove old value before adding
                                 *       new to only be done when drivers only changed */
-                               calculate_fcurve(fcu, ctime);
-                               ok = BKE_animsys_execute_fcurve(ptr, NULL, fcu);
+                               const float curval = calculate_fcurve(fcu, ctime);
+                               ok = BKE_animsys_execute_fcurve(ptr, NULL, fcu, curval);
                                
                                /* clear recalc flag */
                                driver->flag &= ~DRIVER_FLAG_RECALC;
@@ -1753,8 +1753,8 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *
        for (fcu = agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu = fcu->next) {
                /* check if this curve should be skipped */
                if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
-                       calculate_fcurve(fcu, ctime);
-                       BKE_animsys_execute_fcurve(ptr, remap, fcu); 
+                       const float curval = calculate_fcurve(fcu, ctime);
+                       BKE_animsys_execute_fcurve(ptr, remap, fcu, curval);
                }
        }
 }
@@ -2888,8 +2888,8 @@ void BKE_animsys_eval_driver(EvaluationContext *eval_ctx,
                         * NOTE: for 'layering' option later on, we should check if we should remove old value before adding
                         *       new to only be done when drivers only changed */
                        //printf("\told val = %f\n", fcu->curval);
-                       calculate_fcurve(fcu, eval_ctx->ctime);
-                       ok = BKE_animsys_execute_fcurve(&id_ptr, NULL, fcu);
+                       const float curval = calculate_fcurve(fcu, eval_ctx->ctime);
+                       ok = BKE_animsys_execute_fcurve(&id_ptr, NULL, fcu, curval);
                        //printf("\tnew val = %f\n", fcu->curval);
 
                        /* clear recalc flag */
index a2b5a05feac511db3e7d235d126fdd7b5a510667..395161aa6edf8b6937d1544818b1f12651dca9bb 100644 (file)
@@ -2671,7 +2671,7 @@ float evaluate_fcurve(FCurve *fcu, float evaltime)
 }
 
 /* Calculate the value of the given F-Curve at the given frame, and set its curval */
-void calculate_fcurve(FCurve *fcu, float ctime)
+float calculate_fcurve(FCurve *fcu, float evaltime)
 {
        /* only calculate + set curval (overriding the existing value) if curve has 
         * any data which warrants this...
@@ -2680,7 +2680,12 @@ void calculate_fcurve(FCurve *fcu, float ctime)
            list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE))
        {
                /* calculate and set curval (evaluates driver too if necessary) */
-               fcu->curval = evaluate_fcurve(fcu, ctime);
+               float curval = evaluate_fcurve(fcu, evaltime);
+               fcu->curval = curval;  /* debug display only, not thread safe! */
+               return curval;
+       }
+       else {
+               return 0.0f;
        }
 }
 
index c0947dacbf062a3ff3e6995cfae900910aa934bd..8261a211ed08e0d192e5deb346a0f72f5e8fd3e2 100644 (file)
@@ -707,10 +707,13 @@ static void insert_action_keys(bAnimContext *ac, short mode)
                 *                       so it's easier for now to just read the F-Curve directly.
                 *                       (TODO: add the full-blown PointerRNA relative parsing case here...)
                 */
-               if (ale->id && !ale->owner)
+               if (ale->id && !ale->owner) {
                        insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, ts->keyframe_type, flag);
-               else
-                       insert_vert_fcurve(fcu, cfra, fcu->curval, ts->keyframe_type, 0);
+               }
+               else {
+                       const float curval = evaluate_fcurve(fcu, cfra);
+                       insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
+               }
                
                ale->update |= ANIM_UPDATE_DEFAULT;
        }
index f1063996ca3dc8f4ddba91b5d4c85a1359165b79..f38d36853d72a6968f6feffa96157df5f6169cb6 100644 (file)
@@ -606,10 +606,13 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
                         * - fcu->driver != NULL: If this is set, then it's a driver. If we don't check for this, we'd end
                         *                        up adding the keyframes on a new F-Curve in the action data instead.
                         */
-                       if (ale->id && !ale->owner && !fcu->driver)
+                       if (ale->id && !ale->owner && !fcu->driver) {
                                insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, ts->keyframe_type, flag);
-                       else
-                               insert_vert_fcurve(fcu, cfra, fcu->curval, ts->keyframe_type, 0);
+                       }
+                       else {
+                               const float curval = evaluate_fcurve(fcu, cfra);
+                               insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
+                       }
                        
                        ale->update |= ANIM_UPDATE_DEFAULT;
                }
index fdad6aae094d76fce528731712653aeb6488eafb..4c1283452ff874e57066f5f025a2209d43e53420 100644 (file)
@@ -484,7 +484,7 @@ typedef struct FCurve {
        unsigned int totvert;   /* total number of points which define the curve (i.e. size of arrays in FPoints) */
        
                /* value cache + settings */
-       float curval;                   /* value stored from last time curve was evaluated */
+       float curval;                   /* value stored from last time curve was evaluated (not threadsafe, debug display only!) */
        short flag;                             /* user-editable settings for this curve */
        short extend;                   /* value-extending mode for this curve (does not cover  */