T77086 Animation: Passing Dependency Graph to Drivers

Custom driver functions need access to the dependency graph that is
triggering the evaluation of the driver. This patch passes the
dependency graph pointer through all the animation-related calls.

Instead of passing the evaluation time to functions, the code now passes
an `AnimationEvalContext` pointer:

```
typedef struct AnimationEvalContext {
  struct Depsgraph *const depsgraph;
  const float eval_time;
} AnimationEvalContext;
```

These structs are read-only, meaning that the code cannot change the
evaluation time. Note that the `depsgraph` pointer itself is const, but
it points to a non-const depsgraph.

FCurves and Drivers can be evaluated at a different time than the
current scene time, for example when evaluating NLA strips. This means
that, even though the current time is stored in the dependency graph, we
need an explicit evaluation time.

There are two functions that allow creation of `AnimationEvalContext`
objects:

- `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float
  eval_time)`, which creates a new context object from scratch, and
- `BKE_animsys_eval_context_construct_at(AnimationEvalContext
  *anim_eval_context, float eval_time)`, which can be used to create a
  `AnimationEvalContext` with the same depsgraph, but at a different
  time. This makes it possible to later add fields without changing any
  of the code that just want to change the eval time.

This also provides a fix for T75553, although it does require a change
to the custom driver function. The driver should call
`custom_function(depsgraph)`, and the function should use that depsgraph
instead of information from `bpy.context`.

Reviewed By: brecht, sergey

Differential Revision: https://developer.blender.org/D8047
This commit is contained in:
Sybren A. Stüvel 2020-07-17 17:38:09 +02:00 committed by Sybren A. Stüvel
parent 6fbfa522e6
commit 686ab4c940
Notes: blender-bot 2023-02-13 22:55:46 +01:00
Referenced by commit 1c1efe3ac6, Fix memory leak evaluating PyDrivers
Referenced by issue #77086, Passing Dependency Graph to Drivers
Referenced by issue #75553, python unreliable result  for bpy.context.view_layer.name when used in drivers
36 changed files with 503 additions and 183 deletions

View File

@ -32,6 +32,7 @@ extern "C" {
#endif
/* The following structures are defined in DNA_action_types.h, and DNA_anim_types.h */
struct AnimationEvalContext;
struct FCurve;
struct Main;
struct Object;
@ -202,7 +203,7 @@ void what_does_obaction(struct Object *ob,
struct bPose *pose,
struct bAction *act,
char groupname[],
float cframe);
const struct AnimationEvalContext *anim_eval_context);
/* for proxy */
void BKE_pose_copy_pchan_result(struct bPoseChannel *pchanto,

View File

@ -48,6 +48,23 @@ struct bAction;
struct bActionGroup;
struct bContext;
/* Container for data required to do FCurve and Driver evaluation. */
typedef struct AnimationEvalContext {
/* For drivers, so that they have access to the dependency graph and the current view layer. See
* T77086. */
struct Depsgraph *const depsgraph;
/* FCurves and Drivers can be evaluated at a different time than the current scene time, for
* example when evaluating NLA strips. This means that, even though the current time is stored in
* the dependency graph, we need an explicit evaluation time. */
const float eval_time;
} AnimationEvalContext;
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph,
float eval_time);
AnimationEvalContext BKE_animsys_eval_context_construct_at(
const AnimationEvalContext *anim_eval_context, float eval_time);
/* ************************************* */
/* KeyingSets API */
@ -172,11 +189,12 @@ void BKE_fcurves_id_cb(struct ID *id, ID_FCurve_Edit_Callback func, void *user_d
typedef struct NlaKeyframingContext NlaKeyframingContext;
struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *cache,
struct PointerRNA *ptr,
struct AnimData *adt,
float ctime,
const bool flush_to_original);
struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
struct ListBase *cache,
struct PointerRNA *ptr,
struct AnimData *adt,
const struct AnimationEvalContext *anim_eval_context,
const bool flush_to_original);
bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context,
struct PointerRNA *prop_ptr,
struct PropertyRNA *prop,
@ -209,7 +227,7 @@ bool BKE_animsys_write_rna_setting(struct PathResolvedRNA *anim_rna, const float
/* Evaluation loop for evaluating animation data */
void BKE_animsys_evaluate_animdata(struct ID *id,
struct AnimData *adt,
float ctime,
const struct AnimationEvalContext *anim_eval_context,
eAnimData_Recalc recalc,
const bool flush_to_original);
@ -229,14 +247,14 @@ void BKE_animsys_evaluate_all_animation(struct Main *main,
/* Evaluate Action (F-Curve Bag) */
void animsys_evaluate_action(struct PointerRNA *ptr,
struct bAction *act,
float ctime,
const struct AnimationEvalContext *anim_eval_context,
const bool flush_to_original);
/* Evaluate Action Group */
void animsys_evaluate_action_group(struct PointerRNA *ptr,
struct bAction *act,
struct bActionGroup *agrp,
float ctime);
const struct AnimationEvalContext *anim_eval_context);
/* ************************************* */

View File

@ -36,6 +36,7 @@ struct FCurve;
struct FModifier;
struct AnimData;
struct AnimationEvalContext;
struct BezTriple;
struct LibraryForeachIDData;
struct PathResolvedRNA;
@ -281,10 +282,12 @@ float evaluate_fcurve_only_curve(struct FCurve *fcu, float evaltime);
float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna,
struct FCurve *fcu,
struct ChannelDriver *driver_orig,
float evaltime);
const struct AnimationEvalContext *anim_eval_context);
bool BKE_fcurve_is_empty(struct FCurve *fcu);
/* evaluate fcurve and store value */
float calculate_fcurve(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, float evaltime);
float calculate_fcurve(struct PathResolvedRNA *anim_rna,
struct FCurve *fcu,
const struct AnimationEvalContext *anim_eval_context);
/* ************* F-Curve Samples API ******************** */

View File

@ -30,6 +30,7 @@
extern "C" {
#endif
struct AnimationEvalContext;
struct ChannelDriver;
struct DriverTarget;
struct DriverVar;
@ -97,7 +98,7 @@ void BKE_driver_invalidate_expression(struct ChannelDriver *driver,
float evaluate_driver(struct PathResolvedRNA *anim_rna,
struct ChannelDriver *driver,
struct ChannelDriver *driver_orig,
const float evaltime);
const struct AnimationEvalContext *anim_eval_context);
#ifdef __cplusplus
}

View File

@ -1612,8 +1612,12 @@ void BKE_pose_tag_recalc(Main *bmain, bPose *pose)
/* For the calculation of the effects of an Action at the given frame on an object
* This is currently only used for the Action Constraint
*/
void what_does_obaction(
Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe)
void what_does_obaction(Object *ob,
Object *workob,
bPose *pose,
bAction *act,
char groupname[],
const AnimationEvalContext *anim_eval_context)
{
bActionGroup *agrp = BKE_action_group_find_name(act, groupname);
@ -1669,7 +1673,7 @@ void what_does_obaction(
RNA_id_pointer_create(&workob->id, &id_ptr);
/* execute action for this group only */
animsys_evaluate_action_group(&id_ptr, act, agrp, cframe);
animsys_evaluate_action_group(&id_ptr, act, agrp, anim_eval_context);
}
else {
AnimData adt = {NULL};
@ -1680,6 +1684,6 @@ void what_does_obaction(
adt.action = act;
/* execute effects of Action on to workob (or it's PoseChannels) */
BKE_animsys_evaluate_animdata(&workob->id, &adt, cframe, ADT_RECALC_ANIM, false);
BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false);
}
}

View File

@ -538,7 +538,7 @@ static void animsys_write_orig_anim_rna(PointerRNA *ptr,
*/
static void animsys_evaluate_fcurves(PointerRNA *ptr,
ListBase *list,
float ctime,
const AnimationEvalContext *anim_eval_context,
bool flush_to_original)
{
/* Calculate then execute each curve. */
@ -557,7 +557,7 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr,
}
PathResolvedRNA anim_rna;
if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
BKE_animsys_write_rna_setting(&anim_rna, curval);
if (flush_to_original) {
animsys_write_orig_anim_rna(ptr, fcu->rna_path, fcu->array_index, curval);
@ -569,8 +569,26 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr,
/* ***************************************** */
/* Driver Evaluation */
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph,
float eval_time)
{
AnimationEvalContext ctx = {
.depsgraph = depsgraph,
.eval_time = eval_time,
};
return ctx;
}
AnimationEvalContext BKE_animsys_eval_context_construct_at(
const AnimationEvalContext *anim_eval_context, float eval_time)
{
return BKE_animsys_eval_context_construct(anim_eval_context->depsgraph, eval_time);
}
/* Evaluate Drivers */
static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime)
static void animsys_evaluate_drivers(PointerRNA *ptr,
AnimData *adt,
const AnimationEvalContext *anim_eval_context)
{
FCurve *fcu;
@ -591,7 +609,7 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime
* before adding new to only be done when drivers only changed. */
PathResolvedRNA anim_rna;
if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
ok = BKE_animsys_write_rna_setting(&anim_rna, curval);
}
@ -647,7 +665,10 @@ static void action_idcode_patch_check(ID *id, bAction *act)
/* ----------------------------------------- */
/* Evaluate Action Group */
void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *agrp, float ctime)
void animsys_evaluate_action_group(PointerRNA *ptr,
bAction *act,
bActionGroup *agrp,
const AnimationEvalContext *anim_eval_context)
{
FCurve *fcu;
@ -669,7 +690,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *
if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0 && !BKE_fcurve_is_empty(fcu)) {
PathResolvedRNA anim_rna;
if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
BKE_animsys_write_rna_setting(&anim_rna, curval);
}
}
@ -679,7 +700,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *
/* Evaluate Action (F-Curve Bag) */
static void animsys_evaluate_action_ex(PointerRNA *ptr,
bAction *act,
float ctime,
const AnimationEvalContext *anim_eval_context,
const bool flush_to_original)
{
/* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */
@ -690,15 +711,15 @@ static void animsys_evaluate_action_ex(PointerRNA *ptr,
action_idcode_patch_check(ptr->owner_id, act);
/* calculate then execute each curve */
animsys_evaluate_fcurves(ptr, &act->curves, ctime, flush_to_original);
animsys_evaluate_fcurves(ptr, &act->curves, anim_eval_context, flush_to_original);
}
void animsys_evaluate_action(PointerRNA *ptr,
bAction *act,
float ctime,
const AnimationEvalContext *anim_eval_context,
const bool flush_to_original)
{
animsys_evaluate_action_ex(ptr, act, ctime, flush_to_original);
animsys_evaluate_action_ex(ptr, act, anim_eval_context, flush_to_original);
}
/* ***************************************** */
@ -726,7 +747,9 @@ static float nlastrip_get_influence(NlaStrip *strip, float cframe)
}
/* evaluate the evaluation time and influence for the strip, storing the results in the strip */
static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool flush_to_original)
static void nlastrip_evaluate_controls(NlaStrip *strip,
const AnimationEvalContext *anim_eval_context,
const bool flush_to_original)
{
/* now strip's evaluate F-Curves for these settings (if applicable) */
if (strip->fcurves.first) {
@ -736,7 +759,7 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool
RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
/* execute these settings as per normal */
animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, ctime, flush_to_original);
animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, anim_eval_context, flush_to_original);
}
/* analytically generate values for influence and time (if applicable)
@ -744,17 +767,18 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool
* in case the override has been turned off.
*/
if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) {
strip->influence = nlastrip_get_influence(strip, ctime);
strip->influence = nlastrip_get_influence(strip, anim_eval_context->eval_time);
}
/* Bypass evaluation time computation if time mapping is disabled. */
if ((strip->flag & NLASTRIP_FLAG_NO_TIME_MAP) != 0) {
strip->strip_time = ctime;
strip->strip_time = anim_eval_context->eval_time;
return;
}
if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) {
strip->strip_time = nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL);
strip->strip_time = nlastrip_get_frame(
strip, anim_eval_context->eval_time, NLATIME_CONVERT_EVAL);
}
/* if user can control the evaluation time (using F-Curves), consider the option which allows
@ -768,12 +792,16 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool
}
/* gets the strip active at the current time for a list of strips for evaluation purposes */
NlaEvalStrip *nlastrips_ctime_get_strip(
ListBase *list, ListBase *strips, short index, float ctime, const bool flush_to_original)
NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list,
ListBase *strips,
short index,
const AnimationEvalContext *anim_eval_context,
const bool flush_to_original)
{
NlaStrip *strip, *estrip = NULL;
NlaEvalStrip *nes;
short side = 0;
float ctime = anim_eval_context->eval_time;
/* loop over strips, checking if they fall within the range */
for (strip = strips->first; strip; strip = strip->next) {
@ -852,7 +880,9 @@ NlaEvalStrip *nlastrips_ctime_get_strip(
*/
/* TODO: this sounds a bit hacky having a few isolated F-Curves
* stuck on some data it operates on... */
nlastrip_evaluate_controls(estrip, ctime, flush_to_original);
AnimationEvalContext clamped_eval_context = BKE_animsys_eval_context_construct_at(
anim_eval_context, ctime);
nlastrip_evaluate_controls(estrip, &clamped_eval_context, flush_to_original);
if (estrip->influence <= 0.0f) {
return NULL;
}
@ -874,8 +904,12 @@ NlaEvalStrip *nlastrips_ctime_get_strip(
}
/* evaluate controls for the relevant extents of the bordering strips... */
nlastrip_evaluate_controls(estrip->prev, estrip->start, flush_to_original);
nlastrip_evaluate_controls(estrip->next, estrip->end, flush_to_original);
AnimationEvalContext start_eval_context = BKE_animsys_eval_context_construct_at(
anim_eval_context, estrip->start);
AnimationEvalContext end_eval_context = BKE_animsys_eval_context_construct_at(
anim_eval_context, estrip->end);
nlastrip_evaluate_controls(estrip->prev, &start_eval_context, flush_to_original);
nlastrip_evaluate_controls(estrip->next, &end_eval_context, flush_to_original);
break;
}
@ -1795,6 +1829,7 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr,
ListBase *modifiers,
NlaEvalStrip *nes,
NlaEvalSnapshot *snapshot,
const AnimationEvalContext *anim_eval_context,
const bool flush_to_original)
{
ListBase tmp_modifiers = {NULL, NULL};
@ -1836,13 +1871,15 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr,
tmp_nes.strip_mode = NES_TIME_TRANSITION_START;
tmp_nes.strip = s1;
nlaeval_snapshot_init(&snapshot1, channels, snapshot);
nlastrip_evaluate(ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot1, flush_to_original);
nlastrip_evaluate(
ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot1, anim_eval_context, flush_to_original);
/* second strip */
tmp_nes.strip_mode = NES_TIME_TRANSITION_END;
tmp_nes.strip = s2;
nlaeval_snapshot_init(&snapshot2, channels, snapshot);
nlastrip_evaluate(ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot2, flush_to_original);
nlastrip_evaluate(
ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot2, anim_eval_context, flush_to_original);
/* accumulate temp-buffer and full-buffer, using the 'real' strip */
nlaeval_snapshot_mix_and_free(channels, snapshot, &snapshot1, &snapshot2, nes->strip_time);
@ -1857,6 +1894,7 @@ static void nlastrip_evaluate_meta(PointerRNA *ptr,
ListBase *modifiers,
NlaEvalStrip *nes,
NlaEvalSnapshot *snapshot,
const AnimationEvalContext *anim_eval_context,
const bool flush_to_original)
{
ListBase tmp_modifiers = {NULL, NULL};
@ -1877,13 +1915,16 @@ static void nlastrip_evaluate_meta(PointerRNA *ptr,
/* find the child-strip to evaluate */
evaltime = (nes->strip_time * (strip->end - strip->start)) + strip->start;
tmp_nes = nlastrips_ctime_get_strip(NULL, &strip->strips, -1, evaltime, flush_to_original);
AnimationEvalContext child_context = BKE_animsys_eval_context_construct_at(anim_eval_context,
evaltime);
tmp_nes = nlastrips_ctime_get_strip(NULL, &strip->strips, -1, &child_context, flush_to_original);
/* directly evaluate child strip into accumulation buffer...
* - there's no need to use a temporary buffer (as it causes issues [T40082])
*/
if (tmp_nes) {
nlastrip_evaluate(ptr, channels, &tmp_modifiers, tmp_nes, snapshot, flush_to_original);
nlastrip_evaluate(
ptr, channels, &tmp_modifiers, tmp_nes, snapshot, &child_context, flush_to_original);
/* free temp eval-strip */
MEM_freeN(tmp_nes);
@ -1899,6 +1940,7 @@ void nlastrip_evaluate(PointerRNA *ptr,
ListBase *modifiers,
NlaEvalStrip *nes,
NlaEvalSnapshot *snapshot,
const AnimationEvalContext *anim_eval_context,
const bool flush_to_original)
{
NlaStrip *strip = nes->strip;
@ -1921,10 +1963,12 @@ void nlastrip_evaluate(PointerRNA *ptr,
nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes, snapshot);
break;
case NLASTRIP_TYPE_TRANSITION: /* transition */
nlastrip_evaluate_transition(ptr, channels, modifiers, nes, snapshot, flush_to_original);
nlastrip_evaluate_transition(
ptr, channels, modifiers, nes, snapshot, anim_eval_context, flush_to_original);
break;
case NLASTRIP_TYPE_META: /* meta */
nlastrip_evaluate_meta(ptr, channels, modifiers, nes, snapshot, flush_to_original);
nlastrip_evaluate_meta(
ptr, channels, modifiers, nes, snapshot, anim_eval_context, flush_to_original);
break;
default: /* do nothing */
@ -2072,7 +2116,7 @@ static void animsys_evaluate_nla_domain(PointerRNA *ptr, NlaEvalData *channels,
static bool animsys_evaluate_nla(NlaEvalData *echannels,
PointerRNA *ptr,
AnimData *adt,
float ctime,
const AnimationEvalContext *anim_eval_context,
const bool flush_to_original,
NlaKeyframingContext *r_context)
{
@ -2120,7 +2164,8 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels,
}
/* otherwise, get strip to evaluate for this channel */
nes = nlastrips_ctime_get_strip(&estrips, &nlt->strips, track_index, ctime, flush_to_original);
nes = nlastrips_ctime_get_strip(
&estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original);
if (nes) {
nes->track = nlt;
}
@ -2186,7 +2231,8 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels,
/* add this to our list of evaluation strips */
if (r_context == NULL) {
nlastrips_ctime_get_strip(&estrips, &dummy_trackslist, -1, ctime, flush_to_original);
nlastrips_ctime_get_strip(
&estrips, &dummy_trackslist, -1, anim_eval_context, flush_to_original);
}
/* If computing the context for keyframing, store data there instead of the list. */
else {
@ -2196,7 +2242,7 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels,
NLASTRIP_EXTEND_HOLD;
r_context->eval_strip = nes = nlastrips_ctime_get_strip(
NULL, &dummy_trackslist, -1, ctime, flush_to_original);
NULL, &dummy_trackslist, -1, anim_eval_context, flush_to_original);
/* These setting combinations require no data from strips below, so exit immediately. */
if ((nes == NULL) ||
@ -2221,7 +2267,13 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels,
/* 2. for each strip, evaluate then accumulate on top of existing channels,
* but don't set values yet. */
for (nes = estrips.first; nes; nes = nes->next) {
nlastrip_evaluate(ptr, echannels, NULL, nes, &echannels->eval_snapshot, flush_to_original);
nlastrip_evaluate(ptr,
echannels,
NULL,
nes,
&echannels->eval_snapshot,
anim_eval_context,
flush_to_original);
}
/* 3. free temporary evaluation data that's not used elsewhere */
@ -2235,7 +2287,7 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels,
*/
static void animsys_calculate_nla(PointerRNA *ptr,
AnimData *adt,
float ctime,
const AnimationEvalContext *anim_eval_context,
const bool flush_to_original)
{
NlaEvalData echannels;
@ -2243,7 +2295,7 @@ static void animsys_calculate_nla(PointerRNA *ptr,
nlaeval_init(&echannels);
/* evaluate the NLA stack, obtaining a set of values to flush */
if (animsys_evaluate_nla(&echannels, ptr, adt, ctime, flush_to_original, NULL)) {
if (animsys_evaluate_nla(&echannels, ptr, adt, anim_eval_context, flush_to_original, NULL)) {
/* reset any channels touched by currently inactive actions to default value */
animsys_evaluate_nla_domain(ptr, &echannels, adt);
@ -2257,7 +2309,7 @@ static void animsys_calculate_nla(PointerRNA *ptr,
CLOG_WARN(&LOG, "NLA Eval: Stopgap for active action on NLA Stack - no strips case");
}
animsys_evaluate_action(ptr, adt->action, ctime, flush_to_original);
animsys_evaluate_action(ptr, adt->action, anim_eval_context, flush_to_original);
}
/* free temp data */
@ -2275,11 +2327,12 @@ static void animsys_calculate_nla(PointerRNA *ptr,
* \param ptr: RNA pointer to the Object with the animation.
* \return Keyframing context, or NULL if not necessary.
*/
NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *cache,
struct PointerRNA *ptr,
struct AnimData *adt,
float ctime,
const bool flush_to_original)
NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
struct ListBase *cache,
struct PointerRNA *ptr,
struct AnimData *adt,
const AnimationEvalContext *anim_eval_context,
const bool flush_to_original)
{
/* No remapping needed if NLA is off or no action. */
if ((adt == NULL) || (adt->action == NULL) || (adt->nla_tracks.first == NULL) ||
@ -2302,7 +2355,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *ca
ctx->adt = adt;
nlaeval_init(&ctx->nla_channels);
animsys_evaluate_nla(&ctx->nla_channels, ptr, adt, ctime, flush_to_original, ctx);
animsys_evaluate_nla(&ctx->nla_channels, ptr, adt, anim_eval_context, flush_to_original, ctx);
BLI_assert(ELEM(ctx->strip.act, NULL, adt->action));
BLI_addtail(cache, ctx);
@ -2492,8 +2545,11 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt)
* and that the flags for which parts of the anim-data settings need to be recalculated
* have been set already by the depsgraph. Now, we use the recalc
*/
void BKE_animsys_evaluate_animdata(
ID *id, AnimData *adt, float ctime, eAnimData_Recalc recalc, const bool flush_to_original)
void BKE_animsys_evaluate_animdata(ID *id,
AnimData *adt,
const AnimationEvalContext *anim_eval_context,
eAnimData_Recalc recalc,
const bool flush_to_original)
{
PointerRNA id_ptr;
@ -2516,11 +2572,11 @@ void BKE_animsys_evaluate_animdata(
/* evaluate NLA-stack
* - active action is evaluated as part of the NLA stack as the last item
*/
animsys_calculate_nla(&id_ptr, adt, ctime, flush_to_original);
animsys_calculate_nla(&id_ptr, adt, anim_eval_context, flush_to_original);
}
/* evaluate Active Action only */
else if (adt->action) {
animsys_evaluate_action_ex(&id_ptr, adt->action, ctime, flush_to_original);
animsys_evaluate_action_ex(&id_ptr, adt->action, anim_eval_context, flush_to_original);
}
}
@ -2530,7 +2586,7 @@ void BKE_animsys_evaluate_animdata(
* - Drivers should be in the appropriate order to be evaluated without problems...
*/
if (recalc & ADT_RECALC_DRIVERS) {
animsys_evaluate_drivers(&id_ptr, adt, ctime);
animsys_evaluate_drivers(&id_ptr, adt, anim_eval_context);
}
/* always execute 'overrides'
@ -2558,6 +2614,8 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float
}
const bool flush_to_original = DEG_is_active(depsgraph);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
ctime);
/* macros for less typing
* - only evaluate animation data for id if it has users (and not just fake ones)
@ -2568,7 +2626,7 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float
for (id = first; id; id = id->next) { \
if (ID_REAL_USERS(id) > 0) { \
AnimData *adt = BKE_animdata_from_id(id); \
BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \
BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, aflag, flush_to_original); \
} \
} \
(void)0
@ -2587,9 +2645,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float
if (ntp->nodetree) { \
AnimData *adt2 = BKE_animdata_from_id((ID *)ntp->nodetree); \
BKE_animsys_evaluate_animdata( \
&ntp->nodetree->id, adt2, ctime, ADT_RECALC_ANIM, flush_to_original); \
&ntp->nodetree->id, adt2, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); \
} \
BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \
BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, aflag, flush_to_original); \
} \
} \
(void)0
@ -2706,7 +2764,10 @@ void BKE_animsys_eval_animdata(Depsgraph *depsgraph, ID *id)
* which should get handled as part of the dependency graph instead. */
DEG_debug_print_eval_time(depsgraph, __func__, id->name, id, ctime);
const bool flush_to_original = DEG_is_active(depsgraph);
BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM, flush_to_original);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
ctime);
BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original);
}
void BKE_animsys_update_driver_array(ID *id)
@ -2768,7 +2829,9 @@ void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, int driver_index, FCu
if (BKE_animsys_store_rna_setting(&id_ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
/* Evaluate driver, and write results to COW-domain destination */
const float ctime = DEG_get_ctime(depsgraph);
const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
depsgraph, ctime);
const float curval = calculate_fcurve(&anim_rna, fcu, &anim_eval_context);
ok = BKE_animsys_write_rna_setting(&anim_rna, curval);
/* Flush results & status codes to original data for UI (T59984) */

View File

@ -53,6 +53,7 @@
#include "BKE_action.h"
#include "BKE_anim_path.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_bvhutils.h"
#include "BKE_cachefile.h"
@ -2625,7 +2626,7 @@ static void actcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
}
}
static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
static void actcon_get_tarmat(struct Depsgraph *depsgraph,
bConstraint *con,
bConstraintOb *cob,
bConstraintTarget *ct,
@ -2679,6 +2680,8 @@ static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
s = (vec[axis] - data->min) / (data->max - data->min);
CLAMP(s, 0, 1);
t = (s * (data->end - data->start)) + data->start;
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
t);
if (G.debug & G_DEBUG) {
printf("do Action Constraint %s - Ob %s Pchan %s\n",
@ -2693,7 +2696,7 @@ static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
/* evaluate using workob */
/* FIXME: we don't have any consistent standards on limiting effects on object... */
what_does_obaction(cob->ob, &workob, NULL, data->act, NULL, t);
what_does_obaction(cob->ob, &workob, NULL, data->act, NULL, &anim_eval_context);
BKE_object_to_mat4(&workob, ct->matrix);
}
else if (cob->type == CONSTRAINT_OBTYPE_BONE) {
@ -2710,7 +2713,7 @@ static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
tchan->rotmode = pchan->rotmode;
/* evaluate action using workob (it will only set the PoseChannel in question) */
what_does_obaction(cob->ob, &workob, &pose, data->act, pchan->name, t);
what_does_obaction(cob->ob, &workob, &pose, data->act, pchan->name, &anim_eval_context);
/* convert animation to matrices for use here */
BKE_pchan_calc_mat(tchan);

View File

@ -1872,17 +1872,18 @@ float evaluate_fcurve_only_curve(FCurve *fcu, float evaltime)
float evaluate_fcurve_driver(PathResolvedRNA *anim_rna,
FCurve *fcu,
ChannelDriver *driver_orig,
float evaltime)
const AnimationEvalContext *anim_eval_context)
{
BLI_assert(fcu->driver != NULL);
float cvalue = 0.0f;
float evaltime = anim_eval_context->eval_time;
/* If there is a driver (only if this F-Curve is acting as 'driver'),
* evaluate it to find value to use as "evaltime" since drivers essentially act as alternative
* input (i.e. in place of 'time') for F-Curves. */
if (fcu->driver) {
/* evaltime now serves as input for the curve */
evaltime = evaluate_driver(anim_rna, fcu->driver, driver_orig, evaltime);
evaltime = evaluate_driver(anim_rna, fcu->driver, driver_orig, anim_eval_context);
/* only do a default 1-1 mapping if it's unlikely that anything else will set a value... */
if (fcu->totvert == 0) {
@ -1924,7 +1925,9 @@ bool BKE_fcurve_is_empty(FCurve *fcu)
}
/* Calculate the value of the given F-Curve at the given frame, and set its curval */
float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime)
float calculate_fcurve(PathResolvedRNA *anim_rna,
FCurve *fcu,
const AnimationEvalContext *anim_eval_context)
{
/* only calculate + set curval (overriding the existing value) if curve has
* any data which warrants this...
@ -1936,10 +1939,10 @@ float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime)
/* calculate and set curval (evaluates driver too if necessary) */
float curval;
if (fcu->driver) {
curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, evaltime);
curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, anim_eval_context);
}
else {
curval = evaluate_fcurve(fcu, evaltime);
curval = evaluate_fcurve(fcu, anim_eval_context->eval_time);
}
fcu->curval = curval; /* debug display only, not thread safe! */
return curval;

View File

@ -43,6 +43,7 @@
#include "BLT_translation.h"
#include "BKE_action.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_fcurve_driver.h"
@ -1232,24 +1233,25 @@ static void evaluate_driver_min_max(ChannelDriver *driver)
static void evaluate_driver_python(PathResolvedRNA *anim_rna,
ChannelDriver *driver,
ChannelDriver *driver_orig,
const float evaltime)
const AnimationEvalContext *anim_eval_context)
{
/* check for empty or invalid expression */
if ((driver_orig->expression[0] == '\0') || (driver_orig->flag & DRIVER_FLAG_INVALID)) {
driver->curval = 0.0f;
}
else if (!driver_try_evaluate_simple_expr(driver, driver_orig, &driver->curval, evaltime)) {
else if (!driver_try_evaluate_simple_expr(
driver, driver_orig, &driver->curval, anim_eval_context->eval_time)) {
#ifdef WITH_PYTHON
/* this evaluates the expression using Python, and returns its result:
* - on errors it reports, then returns 0.0f
*/
BLI_mutex_lock(&python_driver_lock);
driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, evaltime);
driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, anim_eval_context);
BLI_mutex_unlock(&python_driver_lock);
#else /* WITH_PYTHON*/
UNUSED_VARS(anim_rna, evaltime);
UNUSED_VARS(anim_rna, anim_eval_context);
#endif /* WITH_PYTHON*/
}
}
@ -1262,7 +1264,7 @@ static void evaluate_driver_python(PathResolvedRNA *anim_rna,
float evaluate_driver(PathResolvedRNA *anim_rna,
ChannelDriver *driver,
ChannelDriver *driver_orig,
const float evaltime)
const AnimationEvalContext *anim_eval_context)
{
/* check if driver can be evaluated */
if (driver_orig->flag & DRIVER_FLAG_INVALID) {
@ -1279,7 +1281,7 @@ float evaluate_driver(PathResolvedRNA *anim_rna,
evaluate_driver_min_max(driver);
break;
case DRIVER_TYPE_PYTHON: /* expression */
evaluate_driver_python(anim_rna, driver, driver_orig, evaltime);
evaluate_driver_python(anim_rna, driver, driver_orig, anim_eval_context);
break;
default:
/* special 'hack' - just use stored value

View File

@ -2746,7 +2746,10 @@ void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *o
{
/* Execute drivers and animation. */
const bool flush_to_original = DEG_is_active(depsgraph);
BKE_animsys_evaluate_animdata(&ob->id, ob->adt, ctime, ADT_RECALC_ALL, flush_to_original);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
ctime);
BKE_animsys_evaluate_animdata(
&ob->id, ob->adt, &anim_eval_context, ADT_RECALC_ALL, flush_to_original);
object_where_is_calc_ex(depsgraph, scene, ob, ctime, NULL, NULL);
}
@ -4643,9 +4646,13 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph,
/* was originally ID_RECALC_ALL - TODO - which flags are really needed??? */
/* TODO(sergey): What about animation? */
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
frame);
ob->id.recalc |= ID_RECALC_ALL;
if (update_mesh) {
BKE_animsys_evaluate_animdata(&ob->id, ob->adt, frame, ADT_RECALC_ANIM, flush_to_original);
BKE_animsys_evaluate_animdata(
&ob->id, ob->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original);
/* ignore cache clear during subframe updates
* to not mess up cache validity */
object_cacheIgnoreClear(ob, 1);
@ -4659,12 +4666,14 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph,
/* for curve following objects, parented curve has to be updated too */
if (ob->type == OB_CURVE) {
Curve *cu = ob->data;
BKE_animsys_evaluate_animdata(&cu->id, cu->adt, frame, ADT_RECALC_ANIM, flush_to_original);
BKE_animsys_evaluate_animdata(
&cu->id, cu->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original);
}
/* and armatures... */
if (ob->type == OB_ARMATURE) {
bArmature *arm = ob->data;
BKE_animsys_evaluate_animdata(&arm->id, arm->adt, frame, ADT_RECALC_ANIM, flush_to_original);
BKE_animsys_evaluate_animdata(
&arm->id, arm->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original);
BKE_pose_where_is(depsgraph, scene, ob);
}

View File

@ -4854,8 +4854,10 @@ void particle_system_update(struct Depsgraph *depsgraph,
for (i = 0; i <= part->hair_step; i++) {
hcfra = 100.0f * (float)i / (float)psys->part->hair_step;
if ((part->flag & PART_HAIR_REGROW) == 0) {
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
depsgraph, hcfra);
BKE_animsys_evaluate_animdata(
&part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false);
&part_local->id, part_local->adt, &anim_eval_context, ADT_RECALC_ANIM, false);
}
system_step(&sim, hcfra, use_render_params);
psys->cfra = hcfra;

View File

@ -183,6 +183,10 @@ static float seq_prefetch_cfra(PrefetchJob *pfjob)
{
return pfjob->cfra + pfjob->num_frames_prefetched;
}
static AnimationEvalContext seq_prefetch_anim_eval_context(PrefetchJob *pfjob)
{
return BKE_animsys_eval_context_construct(pfjob->depsgraph, seq_prefetch_cfra(pfjob));
}
void BKE_sequencer_prefetch_get_time_range(Scene *scene, int *start, int *end)
{
@ -435,8 +439,9 @@ static void *seq_prefetch_frames(void *job)
seq_prefetch_update_depsgraph(pfjob);
AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id);
AnimationEvalContext anim_eval_context = seq_prefetch_anim_eval_context(pfjob);
BKE_animsys_evaluate_animdata(
&pfjob->context_cpy.scene->id, adt, seq_prefetch_cfra(pfjob), ADT_RECALC_ALL, false);
&pfjob->context_cpy.scene->id, adt, &anim_eval_context, ADT_RECALC_ALL, false);
/* This is quite hacky solution:
* We need cross-reference original scene with copy for cache.

View File

@ -3361,7 +3361,9 @@ static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr
/* anim-data */
adt = BKE_animdata_from_id(&mask->id);
BKE_animsys_evaluate_animdata(&mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
context->depsgraph, mask->sfra + nr);
BKE_animsys_evaluate_animdata(&mask_temp->id, adt, &anim_eval_context, ADT_RECALC_ANIM, false);
maskbuf = MEM_mallocN(sizeof(float) * context->rectx * context->recty, __func__);

View File

@ -32,6 +32,8 @@
extern "C" {
#endif
struct AnimationEvalContext;
/* --------------- NLA Evaluation DataTypes ----------------------- */
/* used for list of strips to accumulate at current time */
@ -168,13 +170,17 @@ float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode);
/* these functions are only defined here to avoid problems with the order
* in which they get defined. */
NlaEvalStrip *nlastrips_ctime_get_strip(
ListBase *list, ListBase *strips, short index, float ctime, const bool flush_to_original);
NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list,
ListBase *strips,
short index,
const struct AnimationEvalContext *anim_eval_context,
const bool flush_to_original);
void nlastrip_evaluate(PointerRNA *ptr,
NlaEvalData *channels,
ListBase *modifiers,
NlaEvalStrip *nes,
NlaEvalSnapshot *snapshot,
const struct AnimationEvalContext *anim_eval_context,
const bool flush_to_original);
void nladata_flush_channels(PointerRNA *ptr,
NlaEvalData *channels,

View File

@ -4708,6 +4708,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
ReportList *reports = CTX_wm_reports(C);
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
ToolSettings *ts = scene->toolsettings;
ListBase nla_cache = {NULL, NULL};
PointerRNA id_ptr, ptr;
@ -4720,8 +4721,10 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
RNA_id_pointer_create(id, &id_ptr);
/* Get NLA context for value remapping */
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
(float)CFRA);
NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context(
&nla_cache, &id_ptr, adt, (float)CFRA, false);
&nla_cache, &id_ptr, adt, &anim_eval_context, false);
/* get current frame and apply NLA-mapping to it (if applicable) */
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
@ -4738,7 +4741,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
/* insert a keyframe for this F-Curve */
done = insert_keyframe_direct(
reports, ptr, prop, fcu, cfra, ts->keyframe_type, nla_context, flag);
reports, ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, nla_context, flag);
if (done) {
if (adt->action != NULL) {
@ -4762,23 +4765,26 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
ReportList *reports = CTX_wm_reports(C);
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
ToolSettings *ts = scene->toolsettings;
ListBase nla_cache = {NULL, NULL};
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
eInsertKeyFlags flag = 0;
bool done = false;
float cfra;
/* Get RNA pointer */
RNA_id_pointer_create((ID *)key, &id_ptr);
/* Get NLA context for value remapping */
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
(float)CFRA);
NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context(
&nla_cache, &id_ptr, key->adt, (float)CFRA, false);
&nla_cache, &id_ptr, key->adt, &anim_eval_context, false);
/* get current frame and apply NLA-mapping to it (if applicable) */
cfra = BKE_nla_tweakedit_remap(key->adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
const float remapped_frame = BKE_nla_tweakedit_remap(
key->adt, anim_eval_context.eval_time, NLATIME_CONVERT_UNMAP);
/* get flags for keyframing */
flag = ANIM_get_keyframing_flags(scene, true);
@ -4791,13 +4797,21 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
FCurve *fcu = ED_action_fcurve_ensure(bmain, act, NULL, &ptr, rna_path, 0);
/* set the special 'replace' flag if on a keyframe */
if (fcurve_frame_has_keyframe(fcu, cfra, 0)) {
if (fcurve_frame_has_keyframe(fcu, remapped_frame, 0)) {
flag |= INSERTKEY_REPLACE;
}
/* insert a keyframe for this F-Curve */
done = insert_keyframe_direct(
reports, ptr, prop, fcu, cfra, ts->keyframe_type, nla_context, flag);
const AnimationEvalContext remapped_anim_eval_context = BKE_animsys_eval_context_construct_at(
&anim_eval_context, remapped_frame);
done = insert_keyframe_direct(reports,
ptr,
prop,
fcu,
&remapped_anim_eval_context,
ts->keyframe_type,
nla_context,
flag);
if (done) {
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
@ -4848,7 +4862,11 @@ static void achannel_setting_slider_nla_curve_cb(bContext *C,
}
/* insert a keyframe for this F-Curve */
done = insert_keyframe_direct(reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, flag);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
cfra);
done = insert_keyframe_direct(
reports, ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, flag);
if (done) {
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);

View File

@ -419,6 +419,7 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
ac->markers = ED_context_get_markers(C);
}
ac->view_layer = CTX_data_view_layer(C);
ac->depsgraph = CTX_data_depsgraph_pointer(C);
ac->obact = (ac->view_layer->basact) ? ac->view_layer->basact->object : NULL;
ac->area = area;
ac->region = region;

View File

@ -1113,7 +1113,7 @@ static bool insert_keyframe_value(ReportList *reports,
PointerRNA *ptr,
PropertyRNA *prop,
FCurve *fcu,
float cfra,
const AnimationEvalContext *anim_eval_context,
float curval,
eBezTriple_KeyframeType keytype,
eInsertKeyFlags flag)
@ -1130,13 +1130,15 @@ static bool insert_keyframe_value(ReportList *reports,
return false;
}
float cfra = anim_eval_context->eval_time;
/* adjust frame on which to add keyframe */
if ((flag & INSERTKEY_DRIVER) && (fcu->driver)) {
PathResolvedRNA anim_rna;
if (RNA_path_resolved_create(ptr, prop, fcu->array_index, &anim_rna)) {
/* for making it easier to add corrective drivers... */
cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, cfra);
cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, anim_eval_context);
}
else {
cfra = 0.0f;
@ -1202,7 +1204,7 @@ bool insert_keyframe_direct(ReportList *reports,
PointerRNA ptr,
PropertyRNA *prop,
FCurve *fcu,
float cfra,
const AnimationEvalContext *anim_eval_context,
eBezTriple_KeyframeType keytype,
struct NlaKeyframingContext *nla_context,
eInsertKeyFlags flag)
@ -1274,7 +1276,7 @@ bool insert_keyframe_direct(ReportList *reports,
MEM_freeN(values);
}
return insert_keyframe_value(reports, &ptr, prop, fcu, cfra, curval, keytype, flag);
return insert_keyframe_value(reports, &ptr, prop, fcu, anim_eval_context, curval, keytype, flag);
}
/* Find or create the FCurve based on the given path, and insert the specified value into it. */
@ -1286,7 +1288,7 @@ static bool insert_keyframe_fcurve_value(Main *bmain,
const char group[],
const char rna_path[],
int array_index,
float cfra,
const AnimationEvalContext *anim_eval_context,
float curval,
eBezTriple_KeyframeType keytype,
eInsertKeyFlags flag)
@ -1320,12 +1322,35 @@ static bool insert_keyframe_fcurve_value(Main *bmain,
update_autoflags_fcurve_direct(fcu, prop);
/* insert keyframe */
return insert_keyframe_value(reports, ptr, prop, fcu, cfra, curval, keytype, flag);
return insert_keyframe_value(
reports, ptr, prop, fcu, anim_eval_context, curval, keytype, flag);
}
return false;
}
static AnimationEvalContext nla_time_remap(const AnimationEvalContext *anim_eval_context,
PointerRNA *id_ptr,
AnimData *adt,
bAction *act,
ListBase *nla_cache,
NlaKeyframingContext **r_nla_context)
{
if (adt && adt->action == act) {
/* Get NLA context for value remapping. */
*r_nla_context = BKE_animsys_get_nla_keyframing_context(
nla_cache, id_ptr, adt, anim_eval_context, false);
/* Apply NLA-mapping to frame. */
const float remapped_frame = BKE_nla_tweakedit_remap(
adt, anim_eval_context->eval_time, NLATIME_CONVERT_UNMAP);
return BKE_animsys_eval_context_construct_at(anim_eval_context, remapped_frame);
}
*r_nla_context = NULL;
return *anim_eval_context;
}
/**
* Main Keyframing API call
*
@ -1346,7 +1371,7 @@ int insert_keyframe(Main *bmain,
const char group[],
const char rna_path[],
int array_index,
float cfra,
const AnimationEvalContext *anim_eval_context,
eBezTriple_KeyframeType keytype,
ListBase *nla_cache,
eInsertKeyFlags flag)
@ -1393,15 +1418,8 @@ int insert_keyframe(Main *bmain,
/* apply NLA-mapping to frame to use (if applicable) */
adt = BKE_animdata_from_id(id);
if (adt && adt->action == act) {
/* Get NLA context for value remapping. */
nla_context = BKE_animsys_get_nla_keyframing_context(
nla_cache ? nla_cache : &tmp_nla_cache, &id_ptr, adt, cfra, false);
/* Apply NLA-mapping to frame. */
cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
}
const AnimationEvalContext remapped_context = nla_time_remap(
anim_eval_context, &id_ptr, adt, act, nla_cache ? nla_cache : &tmp_nla_cache, &nla_context);
/* Obtain values to insert. */
float value_buffer[RNA_MAX_ARRAY_LENGTH];
@ -1435,7 +1453,7 @@ int insert_keyframe(Main *bmain,
group,
rna_path,
array_index,
cfra,
&remapped_context,
values[array_index],
keytype,
flag)) {
@ -1458,7 +1476,7 @@ int insert_keyframe(Main *bmain,
group,
rna_path,
array_index,
cfra,
&remapped_context,
values[array_index],
keytype,
flag);
@ -1477,7 +1495,7 @@ int insert_keyframe(Main *bmain,
group,
rna_path,
array_index,
cfra,
&remapped_context,
values[array_index],
keytype,
flag);
@ -1495,7 +1513,7 @@ int insert_keyframe(Main *bmain,
group,
rna_path,
array_index,
cfra,
&remapped_context,
values[array_index],
keytype,
flag);
@ -2375,7 +2393,8 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
PropertyRNA *prop = NULL;
char *path;
uiBut *but;
float cfra = (float)CFRA;
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
CTX_data_depsgraph_pointer(C), (float)CFRA);
bool changed = false;
int index;
const bool all = RNA_boolean_get(op->ptr, "all");
@ -2401,7 +2420,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
if (fcu) {
changed = insert_keyframe_direct(
op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, 0);
op->reports, ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, 0);
}
else {
BKE_report(op->reports,
@ -2417,8 +2436,14 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
fcu = BKE_fcurve_find_by_rna_context_ui(C, &ptr, prop, index, NULL, NULL, &driven, &special);
if (fcu && driven) {
changed = insert_keyframe_direct(
op->reports, ptr, prop, fcu, cfra, ts->keyframe_type, NULL, INSERTKEY_DRIVER);
changed = insert_keyframe_direct(op->reports,
ptr,
prop,
fcu,
&anim_eval_context,
ts->keyframe_type,
NULL,
INSERTKEY_DRIVER);
}
}
else {
@ -2461,7 +2486,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
group,
path,
index,
cfra,
&anim_eval_context,
ts->keyframe_type,
NULL,
flag) != 0);
@ -2769,7 +2794,10 @@ bool fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter)
}
/* Returns whether the current value of a given property differs from the interpolated value. */
bool fcurve_is_changed(PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float frame)
bool fcurve_is_changed(PointerRNA ptr,
PropertyRNA *prop,
FCurve *fcu,
const AnimationEvalContext *anim_eval_context)
{
PathResolvedRNA anim_rna;
anim_rna.ptr = ptr;
@ -2780,7 +2808,7 @@ bool fcurve_is_changed(PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float fra
int count, index = fcu->array_index;
float *values = setting_get_rna_values(&ptr, prop, buffer, RNA_MAX_ARRAY_LENGTH, &count);
float fcurve_val = calculate_fcurve(&anim_rna, fcu, frame);
float fcurve_val = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
float cur_val = (index >= 0 && index < count) ? values[index] : 0.0f;
if (values != buffer) {
@ -2987,6 +3015,9 @@ bool ED_autokeyframe_property(
bContext *C, Scene *scene, PointerRNA *ptr, PropertyRNA *prop, int rnaindex, float cfra)
{
Main *bmain = CTX_data_main(C);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
cfra);
ID *id;
bAction *action;
FCurve *fcu;
@ -3007,7 +3038,8 @@ bool ED_autokeyframe_property(
ReportList *reports = CTX_wm_reports(C);
ToolSettings *ts = scene->toolsettings;
changed = insert_keyframe_direct(reports, *ptr, prop, fcu, cfra, ts->keyframe_type, NULL, 0);
changed = insert_keyframe_direct(
reports, *ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, 0);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
}
@ -3020,7 +3052,7 @@ bool ED_autokeyframe_property(
ToolSettings *ts = scene->toolsettings;
changed = insert_keyframe_direct(
reports, *ptr, prop, fcu, cfra, ts->keyframe_type, NULL, INSERTKEY_DRIVER);
reports, *ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, INSERTKEY_DRIVER);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
}
@ -3044,7 +3076,7 @@ bool ED_autokeyframe_property(
((fcu->grp) ? (fcu->grp->name) : (NULL)),
fcu->rna_path,
rnaindex,
cfra,
&anim_eval_context,
ts->keyframe_type,
NULL,
flag) != 0;

View File

@ -1120,6 +1120,9 @@ int ANIM_apply_keyingset(
/* for each possible index, perform operation
* - assume that arraylen is greater than index
*/
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
cfra);
for (; i < arraylen; i++) {
/* action to take depends on mode */
if (mode == MODIFYKEY_MODE_INSERT) {
@ -1130,7 +1133,7 @@ int ANIM_apply_keyingset(
groupname,
ksp->rna_path,
i,
cfra,
&anim_eval_context,
keytype,
&nla_cache,
kflag2);

View File

@ -1023,7 +1023,8 @@ static void poselib_backup_free_data(tPoseLib_PreviewData *pld)
* - gets the string to print in the header
* - this code is based on the code for extract_pose_from_action in blenkernel/action.c
*/
static void poselib_apply_pose(tPoseLib_PreviewData *pld)
static void poselib_apply_pose(tPoseLib_PreviewData *pld,
const AnimationEvalContext *anim_eval_context)
{
PointerRNA *ptr = &pld->rna_ptr;
bArmature *arm = pld->arm;
@ -1049,6 +1050,8 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld)
group_ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
ked.f1 = ((float)frame) - 0.5f;
ked.f2 = ((float)frame) + 0.5f;
AnimationEvalContext anim_context_at_frame = BKE_animsys_eval_context_construct_at(
anim_eval_context, frame);
/* start applying - only those channels which have a key at this point in time! */
for (agrp = act->groups.first; agrp; agrp = agrp->next) {
@ -1075,7 +1078,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld)
}
if (ok) {
animsys_evaluate_action_group(ptr, act, agrp, (float)frame);
animsys_evaluate_action_group(ptr, act, agrp, &anim_context_at_frame);
}
}
}
@ -1150,7 +1153,11 @@ static void poselib_preview_apply(bContext *C, wmOperator *op)
/* pose should be the right one to draw (unless we're temporarily not showing it) */
if ((pld->flag & PL_PREVIEW_SHOWORIGINAL) == 0) {
RNA_int_set(op->ptr, "pose_index", BLI_findindex(&pld->act->markers, pld->marker));
poselib_apply_pose(pld);
struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
depsgraph, 0.0f /* poselib_apply_pose() determines its own evaluation time. */);
poselib_apply_pose(pld, &anim_eval_context);
}
else {
RNA_int_set(op->ptr, "pose_index", -2); /* -2 means don't apply any pose */

View File

@ -1219,7 +1219,9 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
float cframe = (float)CFRA;
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
(float)CFRA);
const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
@ -1240,7 +1242,8 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
workob.adt = ob->adt;
workob.pose = dummyPose;
BKE_animsys_evaluate_animdata(&workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false);
BKE_animsys_evaluate_animdata(
&workob.id, workob.adt, &anim_eval_context, ADT_RECALC_ANIM, false);
/* copy back values, but on selected bones only */
for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {

View File

@ -48,6 +48,7 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "BKE_animsys.h"
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@ -399,6 +400,7 @@ static void gpencil_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd,
static void gpencil_stroke_path_animation_add_keyframes(ReportList *reports,
PointerRNA ptr,
PropertyRNA *prop,
Depsgraph *depsgraph,
FCurve *fcu,
Curve *cu,
tGpTimingData *gtd,
@ -453,8 +455,16 @@ static void gpencil_stroke_path_animation_add_keyframes(ReportList *reports,
if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
cfra = last_valid_time + MIN_TIME_DELTA;
}
insert_keyframe_direct(
reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
depsgraph, cfra);
insert_keyframe_direct(reports,
ptr,
prop,
fcu,
&anim_eval_context,
BEZT_KEYTYPE_KEYFRAME,
NULL,
INSERTKEY_FAST);
last_valid_time = cfra;
}
else if (G.debug & G_DEBUG) {
@ -466,8 +476,16 @@ static void gpencil_stroke_path_animation_add_keyframes(ReportList *reports,
if ((cfra - last_valid_time) < MIN_TIME_DELTA) {
cfra = last_valid_time + MIN_TIME_DELTA;
}
insert_keyframe_direct(
reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
cfra);
insert_keyframe_direct(reports,
ptr,
prop,
fcu,
&anim_eval_context,
BEZT_KEYTYPE_KEYFRAME,
NULL,
INSERTKEY_FAST);
last_valid_time = cfra;
}
else {
@ -475,8 +493,16 @@ static void gpencil_stroke_path_animation_add_keyframes(ReportList *reports,
* and also far enough from (not yet added!) end_stroke keyframe!
*/
if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) {
insert_keyframe_direct(
reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_BREAKDOWN, NULL, INSERTKEY_FAST);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
depsgraph, cfra);
insert_keyframe_direct(reports,
ptr,
prop,
fcu,
&anim_eval_context,
BEZT_KEYTYPE_BREAKDOWN,
NULL,
INSERTKEY_FAST);
last_valid_time = cfra;
}
else if (G.debug & G_DEBUG) {
@ -496,6 +522,7 @@ static void gpencil_stroke_path_animation(bContext *C,
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
bAction *act;
FCurve *fcu;
PointerRNA ptr;
@ -537,8 +564,16 @@ static void gpencil_stroke_path_animation(bContext *C,
cu->ctime = 0.0f;
cfra = (float)gtd->start_frame;
insert_keyframe_direct(
reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
AnimationEvalContext anim_eval_context_start = BKE_animsys_eval_context_construct(depsgraph,
cfra);
insert_keyframe_direct(reports,
ptr,
prop,
fcu,
&anim_eval_context_start,
BEZT_KEYTYPE_KEYFRAME,
NULL,
INSERTKEY_FAST);
cu->ctime = cu->pathlen;
if (gtd->realtime) {
@ -547,8 +582,16 @@ static void gpencil_stroke_path_animation(bContext *C,
else {
cfra = (float)gtd->end_frame;
}
insert_keyframe_direct(
reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, NULL, INSERTKEY_FAST);
AnimationEvalContext anim_eval_context_end = BKE_animsys_eval_context_construct(depsgraph,
cfra);
insert_keyframe_direct(reports,
ptr,
prop,
fcu,
&anim_eval_context_end,
BEZT_KEYTYPE_KEYFRAME,
NULL,
INSERTKEY_FAST);
}
else {
/* Use actual recorded timing! */
@ -575,7 +618,7 @@ static void gpencil_stroke_path_animation(bContext *C,
}
gpencil_stroke_path_animation_add_keyframes(
reports, ptr, prop, fcu, cu, gtd, rng, time_range, nbr_gaps, tot_gaps_time);
reports, ptr, prop, depsgraph, fcu, cu, gtd, rng, time_range, nbr_gaps, tot_gaps_time);
BLI_rng_free(rng);
}

View File

@ -95,6 +95,8 @@ typedef struct bAnimContext {
struct Scene *scene;
/** active scene layer */
struct ViewLayer *view_layer;
/** active dependency graph */
struct Depsgraph *depsgraph;
/** active object */
struct Object *obact;
/** active set of markers */

View File

@ -38,6 +38,7 @@ struct Scene;
struct KeyingSet;
struct AnimationEvalContext;
struct BezTriple;
struct FCurve;
struct bAction;
@ -118,7 +119,7 @@ bool insert_keyframe_direct(struct ReportList *reports,
struct PointerRNA ptr,
struct PropertyRNA *prop,
struct FCurve *fcu,
float cfra,
const struct AnimationEvalContext *anim_eval_context,
eBezTriple_KeyframeType keytype,
struct NlaKeyframingContext *nla,
eInsertKeyFlags flag);
@ -136,7 +137,7 @@ int insert_keyframe(struct Main *bmain,
const char group[],
const char rna_path[],
int array_index,
float cfra,
const struct AnimationEvalContext *anim_eval_context,
eBezTriple_KeyframeType keytype,
struct ListBase *nla_cache,
eInsertKeyFlags flag);
@ -458,7 +459,7 @@ bool fcurve_frame_has_keyframe(struct FCurve *fcu, float frame, short filter);
bool fcurve_is_changed(struct PointerRNA ptr,
struct PropertyRNA *prop,
struct FCurve *fcu,
float frame);
const struct AnimationEvalContext *anim_eval_context);
/**
* Main Keyframe Checking API call:

View File

@ -44,6 +44,7 @@
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
@ -1733,6 +1734,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
wmWindow *window = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
ARegion *region = CTX_wm_region(C);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
uiBut *but;
BLI_assert(block->active);
@ -1761,7 +1763,9 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
}
}
ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
depsgraph, (scene) ? scene->r.cfra : 0.0f);
ui_but_anim_flag(but, &anim_eval_context);
ui_but_override_flag(CTX_data_main(C), but);
if (UI_but_is_decorator(but)) {
ui_but_anim_decorate_update_from_flag(but);

View File

@ -33,6 +33,7 @@
#include "BLI_string_utf8.h"
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_fcurve_driver.h"
@ -65,7 +66,7 @@ static FCurve *ui_but_get_fcurve(
but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, adt, action, r_driven, r_special);
}
void ui_but_anim_flag(uiBut *but, float cfra)
void ui_but_anim_flag(uiBut *but, const AnimationEvalContext *anim_eval_context)
{
AnimData *adt;
bAction *act;
@ -95,6 +96,7 @@ void ui_but_anim_flag(uiBut *but, float cfra)
* we need to correct the frame number to "look inside" the
* remapped action
*/
float cfra = anim_eval_context->eval_time;
if (adt) {
cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
}
@ -105,7 +107,9 @@ void ui_but_anim_flag(uiBut *but, float cfra)
/* XXX: this feature is totally broken and useless with NLA */
if (adt == NULL || adt->nla_tracks.first == NULL) {
if (fcurve_is_changed(but->rnapoin, but->rnaprop, fcu, cfra)) {
const AnimationEvalContext remapped_context = BKE_animsys_eval_context_construct_at(
anim_eval_context, cfra);
if (fcurve_is_changed(but->rnapoin, but->rnaprop, fcu, &remapped_context)) {
but->drawflag |= UI_BUT_ANIMATED_CHANGED;
}
}

View File

@ -47,6 +47,7 @@
#include "PIL_time.h"
#include "BKE_animsys.h"
#include "BKE_blender_undo.h"
#include "BKE_brush.h"
#include "BKE_colorband.h"
@ -8408,6 +8409,9 @@ void UI_context_update_anim_flag(const bContext *C)
{
Scene *scene = CTX_data_scene(C);
ARegion *region = CTX_wm_region(C);
struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
depsgraph, (scene) ? scene->r.cfra : 0.0f);
uiBlock *block;
uiBut *but, *activebut;
@ -8417,7 +8421,7 @@ void UI_context_update_anim_flag(const bContext *C)
for (block = region->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next) {
ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
ui_but_anim_flag(but, &anim_eval_context);
ui_but_override_flag(CTX_data_main(C), but);
if (UI_but_is_decorator(but)) {
ui_but_anim_decorate_update_from_flag(but);

View File

@ -32,6 +32,7 @@
#include "UI_interface.h"
#include "UI_resources.h"
struct AnimationEvalContext;
struct ARegion;
struct ID;
struct ImBuf;
@ -938,7 +939,7 @@ int ui_but_align_opposite_to_area_align_get(const struct ARegion *region) ATTR_W
void ui_block_align_calc(uiBlock *block, const struct ARegion *region);
/* interface_anim.c */
void ui_but_anim_flag(uiBut *but, float cfra);
void ui_but_anim_flag(uiBut *but, const struct AnimationEvalContext *anim_eval_context);
void ui_but_anim_copy_driver(struct bContext *C);
void ui_but_anim_paste_driver(struct bContext *C);
bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen);

View File

@ -2796,12 +2796,16 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
cfra = scene->r.cfra;
/* precalculate time variable before baking */
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
for (f = omd->bakestart; f <= omd->bakeend; f++) {
/* For now only simple animation of time value is supported, nothing else.
* No drivers or other modifier parameters. */
/* TODO(sergey): This operates on an original data, so no flush is needed. However, baking
* usually should happen on an evaluated objects, so this seems to be deeper issue here. */
BKE_animsys_evaluate_animdata((ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
f);
BKE_animsys_evaluate_animdata((ID *)ob, ob->adt, &anim_eval_context, ADT_RECALC_ANIM, false);
och->time[i] = omd->time;
i++;

View File

@ -724,9 +724,10 @@ static void insert_action_keys(bAnimContext *ac, short mode)
flag = ANIM_get_keyframing_flags(scene, true);
/* insert keyframes */
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(ac->depsgraph,
(float)CFRA);
for (ale = anim_data.first; ale; ale = ale->next) {
FCurve *fcu = (FCurve *)ale->key_data;
float cfra = (float)CFRA;
/* Read value from property the F-Curve represents, or from the curve only?
* - ale->id != NULL:
@ -745,7 +746,7 @@ static void insert_action_keys(bAnimContext *ac, short mode)
((fcu->grp) ? (fcu->grp->name) : (NULL)),
fcu->rna_path,
fcu->array_index,
cfra,
&anim_eval_context,
ts->keyframe_type,
&nla_cache,
flag);
@ -754,8 +755,9 @@ static void insert_action_keys(bAnimContext *ac, short mode)
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
/* adjust current frame for NLA-scaling */
float cfra = anim_eval_context.eval_time;
if (adt) {
cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
}
const float curval = evaluate_fcurve(fcu, cfra);

View File

@ -681,9 +681,10 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
}
}
else {
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
ac->depsgraph, (float)CFRA);
for (ale = anim_data.first; ale; ale = ale->next) {
FCurve *fcu = (FCurve *)ale->key_data;
float cfra = (float)CFRA;
/* Read value from property the F-Curve represents, or from the curve only?
*
@ -705,7 +706,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
((fcu->grp) ? (fcu->grp->name) : (NULL)),
fcu->rna_path,
fcu->array_index,
cfra,
&anim_eval_context,
ts->keyframe_type,
&nla_cache,
flag);
@ -714,6 +715,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
/* adjust current frame for NLA-mapping */
float cfra = (float)CFRA;
if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS)) {
cfra = sipo->cursorTime;
}

View File

@ -115,7 +115,9 @@ static void autokeyframe_pose(
ToolSettings *ts = scene->toolsettings;
KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
ListBase nla_cache = {NULL, NULL};
float cfra = (float)CFRA;
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
(float)CFRA);
eInsertKeyFlags flag = 0;
/* flag is initialized from UserPref keyframing settings
@ -146,7 +148,8 @@ static void autokeyframe_pose(
/* only insert into active keyingset? */
if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
/* run the active Keying Set on the current datasource */
ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
ANIM_apply_keyingset(
C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
}
/* only insert into available channels? */
else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
@ -169,7 +172,7 @@ static void autokeyframe_pose(
((fcu->grp) ? (fcu->grp->name) : (NULL)),
fcu->rna_path,
fcu->array_index,
cfra,
&anim_eval_context,
ts->keyframe_type,
&nla_cache,
flag);
@ -220,21 +223,25 @@ static void autokeyframe_pose(
if (do_loc) {
KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
ANIM_apply_keyingset(
C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
}
if (do_rot) {
KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
ANIM_apply_keyingset(
C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
}
if (do_scale) {
KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
ANIM_apply_keyingset(
C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
}
}
/* insert keyframe in all (transform) channels */
else {
KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
ANIM_apply_keyingset(
C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
}
/* free temp info */

View File

@ -794,7 +794,9 @@ static void autokeyframe_object(
ToolSettings *ts = scene->toolsettings;
KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
ListBase dsources = {NULL, NULL};
float cfra = (float)CFRA; // xxx this will do for now
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
(float)CFRA);
eInsertKeyFlags flag = 0;
/* Get flags used for inserting keyframes. */
@ -808,7 +810,8 @@ static void autokeyframe_object(
* NOTE: we assume here that the active Keying Set
* does not need to have its iterator overridden.
*/
ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
ANIM_apply_keyingset(
C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
}
else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) {
AnimData *adt = ob->adt;
@ -824,7 +827,7 @@ static void autokeyframe_object(
(fcu->grp ? fcu->grp->name : NULL),
fcu->rna_path,
fcu->array_index,
cfra,
&anim_eval_context,
ts->keyframe_type,
&nla_cache,
flag);
@ -872,21 +875,25 @@ static void autokeyframe_object(
/* insert keyframes for the affected sets of channels using the builtin KeyingSets found */
if (do_loc) {
KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
ANIM_apply_keyingset(
C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
}
if (do_rot) {
KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
ANIM_apply_keyingset(
C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
}
if (do_scale) {
KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
ANIM_apply_keyingset(
C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
}
}
/* insert keyframe in all (transform) channels */
else {
KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
ANIM_apply_keyingset(
C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, anim_eval_context.eval_time);
}
/* free temp info */

View File

@ -21,6 +21,7 @@
#ifndef __BPY_EXTERN_H__
#define __BPY_EXTERN_H__
struct AnimationEvalContext;
struct ChannelDriver; /* DNA_anim_types.h */
struct ID; /* DNA_ID.h */
struct ListBase; /* DNA_listBase.h */
@ -117,7 +118,7 @@ void BPY_driver_reset(void);
float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
struct ChannelDriver *driver,
struct ChannelDriver *driver_orig,
const float evaltime);
const struct AnimationEvalContext *anim_eval_context);
void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */
void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr);

View File

@ -33,19 +33,22 @@
#include "BLI_math_base.h"
#include "BLI_string.h"
#include "BKE_animsys.h"
#include "BKE_fcurve_driver.h"
#include "BKE_global.h"
#include "RNA_access.h"
#include "RNA_types.h"
#include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */
#include "bpy_intern_string.h"
#include "bpy_driver.h"
#include "bpy_rna.h"
#include "BPY_extern.h"
extern void BPY_update_rna_module(void);
#define USE_RNA_AS_PYOBJECT
#define USE_BYTECODE_WHITELIST
@ -377,6 +380,37 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d
#endif /* USE_BYTECODE_WHITELIST */
static PyObject *bpy_pydriver_depsgraph_as_pyobject(struct Depsgraph *depsgraph)
{
/* This should never happen, but it's probably better to have None in Python
* than a NULL-wrapping Depsgraph py struct. */
BLI_assert(depsgraph != NULL);
if (depsgraph == NULL) {
Py_RETURN_NONE;
}
struct PointerRNA depsgraph_ptr;
RNA_pointer_create(NULL, &RNA_Depsgraph, depsgraph, &depsgraph_ptr);
return pyrna_struct_CreatePyObject(&depsgraph_ptr);
}
/* Adds a variable 'depsgraph' to the driver variables. This can then be used to obtain evaluated
* datablocks, and the current view layer and scene. See T75553. */
static void bpy_pydriver_namespace_add_depsgraph(PyObject *driver_vars,
struct Depsgraph *depsgraph)
{
PyObject *py_depsgraph = bpy_pydriver_depsgraph_as_pyobject(depsgraph);
const char *depsgraph_variable_name = "depsgraph";
if (PyDict_SetItemString(driver_vars, depsgraph_variable_name, py_depsgraph) == -1) {
fprintf(stderr,
"\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n",
depsgraph_variable_name);
PyErr_Print();
PyErr_Clear();
}
}
/* This evals py driver expressions, 'expr' is a Python expression that
* should evaluate to a float number, which is returned.
*
@ -396,7 +430,7 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d
float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
ChannelDriver *driver,
ChannelDriver *driver_orig,
const float evaltime)
const AnimationEvalContext *anim_eval_context)
{
PyObject *driver_vars = NULL;
PyObject *retval = NULL;
@ -456,7 +490,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
}
/* update global namespace */
bpy_pydriver_namespace_update_frame(evaltime);
bpy_pydriver_namespace_update_frame(anim_eval_context->eval_time);
if (driver_orig->flag & DRIVER_FLAG_USE_SELF) {
bpy_pydriver_namespace_update_self(anim_rna);
@ -589,6 +623,8 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
}
#endif /* USE_BYTECODE_WHITELIST */
bpy_pydriver_namespace_add_depsgraph(driver_vars, anim_eval_context->depsgraph);
#if 0 /* slow, with this can avoid all Py_CompileString above. */
/* execute expression to get a value */
retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);

View File

@ -36,6 +36,7 @@
#include "ED_keyframing.h"
#include "BKE_anim_data.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
@ -332,7 +333,20 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
&options) == -1) {
return NULL;
}
else if (self->ptr.type == &RNA_NlaStrip) {
/* This assumes that keyframes are only added on original data & using the active depsgraph. If
* it turns out to be necessary for some reason to insert keyframes on evaluated objects, we can
* revisit this and add an explicit `depsgraph` keyword argument to the function call.
*
* It is unlikely that driver code (which is the reason this depsgraph pointer is obtained) will
* be executed from this function call, as this only happens when `options` has
* `INSERTKEY_DRIVER`, which is not exposed to Python. */
bContext *C = BPy_GetContext();
struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
cfra);
if (self->ptr.type == &RNA_NlaStrip) {
/* Handle special properties for NLA Strips, whose F-Curves are stored on the
* strips themselves. These are stored separately or else the properties will
* not have any effect.
@ -355,8 +369,8 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
if (prop) {
NlaStrip *strip = ptr.data;
FCurve *fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), index);
result = insert_keyframe_direct(&reports, ptr, prop, fcu, cfra, keytype, NULL, options);
result = insert_keyframe_direct(
&reports, ptr, prop, fcu, &anim_eval_context, keytype, NULL, options);
}
else {
BKE_reportf(&reports, RPT_ERROR, "Could not resolve path (%s)", path_full);
@ -384,7 +398,7 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
group_name,
path_full,
index,
cfra,
&anim_eval_context,
keytype,
NULL,
options) != 0);

View File

@ -2493,7 +2493,9 @@ void RE_RenderAnim(Render *re,
{
float ctime = BKE_scene_frame_get(scene);
AnimData *adt = BKE_animdata_from_id(&scene->id);
BKE_animsys_evaluate_animdata(&scene->id, adt, ctime, ADT_RECALC_ALL, false);
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
re->pipeline_depsgraph, ctime);
BKE_animsys_evaluate_animdata(&scene->id, adt, &anim_eval_context, ADT_RECALC_ALL, false);
}
render_update_depsgraph(re);