Fix T48234: Glitch w/ action constraints sharing an action

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.
This commit is contained in:
Campbell Barton 2016-06-04 00:54:28 +10:00
parent 398180439b
commit c6cc599311
Notes: blender-bot 2023-02-14 10:04:50 +01:00
Referenced by issue #50346, Regression between 2.77 and 2.78 in some armature/animation evaluation cases
Referenced by issue #48234, Bone Action Constraints with shared Action leads to glitches
7 changed files with 32 additions and 21 deletions

View 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

View 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 ******************** */

View 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 */

View 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;
}
}

View 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;
}

View 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;
}

View 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 */