diff options
Diffstat (limited to 'source/blender/blenkernel/intern/anim_sys.c')
-rw-r--r-- | source/blender/blenkernel/intern/anim_sys.c | 608 |
1 files changed, 292 insertions, 316 deletions
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index b17bc70c51a..351e765a8ea 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -57,27 +57,27 @@ #include "DNA_texture_types.h" #include "DNA_world_types.h" -#include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_animsys.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" -#include "BKE_nla.h" #include "BKE_global.h" +#include "BKE_library.h" #include "BKE_main.h" #include "BKE_material.h" -#include "BKE_library.h" +#include "BKE_nla.h" #include "BKE_report.h" #include "BKE_texture.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + #include "RNA_access.h" #include "nla_private.h" #include "atomic_ops.h" -#include "DEG_depsgraph.h" - /* ***************************************** */ /* AnimData API */ @@ -97,6 +97,7 @@ bool id_type_can_have_animdata(const short id_type) case ID_MA: case ID_TE: case ID_NT: case ID_LA: case ID_CA: case ID_WO: case ID_LS: + case ID_LP: case ID_SPK: case ID_SCE: case ID_MC: @@ -245,11 +246,14 @@ void BKE_animdata_free(ID *id, const bool do_id_user) } /* free nla data */ - BKE_nla_tracks_free(&adt->nla_tracks); + BKE_nla_tracks_free(&adt->nla_tracks, do_id_user); /* free drivers - stored as a list of F-Curves */ free_fcurves(&adt->drivers); + /* free driver array cache */ + MEM_SAFE_FREE(adt->driver_array); + /* free overrides */ /* TODO... */ @@ -262,11 +266,18 @@ void BKE_animdata_free(ID *id, const bool do_id_user) /* Copying -------------------------------------------- */ -/* Make a copy of the given AnimData - to be used when copying datablocks */ -AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action) +/** + * Make a copy of the given AnimData - to be used when copying datablocks. + * \param flag Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_... flags in BKE_library.h + * \return The copied animdata. + */ +AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag) { AnimData *dadt; + const bool do_action = (flag & LIB_ID_COPY_ACTIONS) != 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0; + const bool do_id_user = (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0; + /* sanity check before duplicating struct */ if (adt == NULL) return NULL; @@ -278,16 +289,17 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action) BKE_id_copy_ex(bmain, (ID *)dadt->action, (ID **)&dadt->action, 0, false); BKE_id_copy_ex(bmain, (ID *)dadt->tmpact, (ID **)&dadt->tmpact, 0, false); } - else { + else if (do_id_user) { id_us_plus((ID *)dadt->action); id_us_plus((ID *)dadt->tmpact); } /* duplicate NLA data */ - BKE_nla_tracks_copy(bmain, &dadt->nla_tracks, &adt->nla_tracks); + BKE_nla_tracks_copy(bmain, &dadt->nla_tracks, &adt->nla_tracks, flag); /* duplicate drivers (F-Curves) */ copy_fcurves(&dadt->drivers, &adt->drivers); + dadt->driver_array = NULL; /* don't copy overrides */ BLI_listbase_clear(&dadt->overrides); @@ -296,19 +308,23 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action) return dadt; } -bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const bool do_action) +/** + * \param flag Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_... flags in BKE_library.h + * \return true is succesfully copied. + */ +bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const int flag) { AnimData *adt; if ((id_to && id_from) && (GS(id_to->name) != GS(id_from->name))) return false; - BKE_animdata_free(id_to, true); + BKE_animdata_free(id_to, (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0); adt = BKE_animdata_from_id(id_from); if (adt) { IdAdtTemplate *iat = (IdAdtTemplate *)id_to; - iat->adt = BKE_animdata_copy(bmain, adt, do_action); + iat->adt = BKE_animdata_copy(bmain, adt, flag); } return true; @@ -368,7 +384,7 @@ void BKE_animdata_merge_copy( if (src->nla_tracks.first) { ListBase tracks = {NULL, NULL}; - BKE_nla_tracks_copy(bmain, &tracks, &src->nla_tracks); + BKE_nla_tracks_copy(bmain, &tracks, &src->nla_tracks, 0); BLI_movelisttolist(&dst->nla_tracks, &tracks); } @@ -604,36 +620,8 @@ char *BKE_animdata_driver_path_hack(bContext *C, PointerRNA *ptr, PropertyRNA *p Object *ob = CTX_data_active_object(C); if (ob && id) { - /* only id-types which can be remapped to go through objects should be considered */ - switch (GS(id->name)) { - case ID_TE: /* textures */ - { - Material *ma = give_current_material(ob, ob->actcol); - Tex *tex = give_current_material_texture(ma); - - /* assumes: texture will only be shown if it is active material's active texture it's ok */ - if ((ID *)tex == id) { - char name_esc_ma[(sizeof(ma->id.name) - 2) * 2]; - char name_esc_tex[(sizeof(tex->id.name) - 2) * 2]; - - BLI_strescape(name_esc_ma, ma->id.name + 2, sizeof(name_esc_ma)); - BLI_strescape(name_esc_tex, tex->id.name + 2, sizeof(name_esc_tex)); - - /* create new path */ - // TODO: use RNA path functions to construct step by step instead? - // FIXME: maybe this isn't even needed anymore... - path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s", - name_esc_ma, name_esc_tex, basepath); - - /* free old one */ - if (basepath != base_path) - MEM_freeN(basepath); - } - break; - } - default: - break; - } + /* TODO: after material textures were removed, this function serves + * no purpose anymore, but could be used again so was not removed. */ /* fix RNA pointer, as we've now changed the ID root by changing the paths */ if (basepath != path) { @@ -1173,6 +1161,9 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use /* grease pencil */ ANIMDATA_IDS_CB(bmain->gpencil.first); + /* palettes */ + ANIMDATA_IDS_CB(bmain->palettes.first); + /* cache files */ ANIMDATA_IDS_CB(bmain->cachefiles.first); } @@ -1477,42 +1468,14 @@ void BKE_keyingsets_free(ListBase *list) /* ***************************************** */ /* Evaluation Data-Setting Backend */ -/* Retrieve string to act as RNA-path, adjusted using mapping-table if provided - * It returns whether the string needs to be freed (i.e. if it was a temp remapped one) - * // FIXME: maybe it would be faster if we didn't have to alloc/free strings like this all the time, but for now it's safer - * - * - remap: remapping table to use - * - path: original path string (as stored in F-Curve data) - * - dst: destination string to write data to - */ -static bool animsys_remap_path(AnimMapper *UNUSED(remap), char *path, char **dst) -{ - /* is there a valid remapping table to use? */ -#if 0 - if (remap) { - /* find a matching entry... to use to remap */ - /* ...TODO... */ - } -#endif - - /* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */ - *dst = path; - return false; -} - static bool animsys_store_rna_setting( - PointerRNA *ptr, AnimMapper *remap, + PointerRNA *ptr, /* typically 'fcu->rna_path', 'fcu->array_index' */ const char *rna_path, const int array_index, PathResolvedRNA *r_result) { bool success = false; - - char *path = NULL; - bool free_path; - - /* get path, remapped as appropriate to work in its new environment */ - free_path = animsys_remap_path(remap, (char *)rna_path, &path); + const char *path = rna_path; /* write value to setting */ if (path) { @@ -1546,11 +1509,6 @@ static bool animsys_store_rna_setting( } } - /* free temp path-info */ - if (free_path) { - MEM_freeN((void *)path); - } - return success; } @@ -1558,6 +1516,72 @@ static bool animsys_store_rna_setting( /* less than 1.0 evaluates to false, use epsilon to avoid float error */ #define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON))) +static bool animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value) +{ + PropertyRNA *prop = anim_rna->prop; + PointerRNA *ptr = &anim_rna->ptr; + int array_index = anim_rna->prop_index; + float orig_value; + + /* caller must ensure this is animatable */ + BLI_assert(RNA_property_animateable(ptr, prop) || ptr->id.data == NULL); + + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: + { + if (array_index != -1) { + const int orig_value_coerce = RNA_property_boolean_get_index(ptr, prop, array_index); + orig_value = (float)orig_value_coerce; + } + else { + const int orig_value_coerce = RNA_property_boolean_get(ptr, prop); + orig_value = (float)orig_value_coerce; + } + break; + } + case PROP_INT: + { + if (array_index != -1) { + const int orig_value_coerce = RNA_property_int_get_index(ptr, prop, array_index); + orig_value = (float)orig_value_coerce; + } + else { + const int orig_value_coerce = RNA_property_int_get(ptr, prop); + orig_value = (float)orig_value_coerce; + } + break; + } + case PROP_FLOAT: + { + if (array_index != -1) { + const float orig_value_coerce = RNA_property_float_get_index(ptr, prop, array_index); + orig_value = (float)orig_value_coerce; + } + else { + const float orig_value_coerce = RNA_property_float_get(ptr, prop); + orig_value = (float)orig_value_coerce; + } + break; + } + case PROP_ENUM: + { + const int orig_value_coerce = RNA_property_enum_get(ptr, prop); + orig_value = (float)orig_value_coerce; + break; + } + default: + /* nothing can be done here... so it is unsuccessful? */ + return false; + } + + if (r_value != NULL) { + *r_value = orig_value; + } + + /* successful */ + return true; +} + /* Write the given value to a setting using RNA, and return success */ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float value) { @@ -1568,27 +1592,24 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val /* caller must ensure this is animatable */ BLI_assert(RNA_property_animateable(ptr, prop) || ptr->id.data == NULL); - /* set value for animatable numerical values only - * HACK: some local F-Curves (e.g. those on NLA Strips) are evaluated - * without an ID provided, which causes the animateable test to fail! - */ - bool written = false; + /* Check whether value is new. Otherwise we skip all the updates. */ + float old_value; + if (!animsys_read_rna_setting(anim_rna, &old_value)) { + return false; + } + if (old_value == value) { + return true; + } switch (RNA_property_type(prop)) { case PROP_BOOLEAN: { const int value_coerce = ANIMSYS_FLOAT_AS_BOOL(value); if (array_index != -1) { - if (RNA_property_boolean_get_index(ptr, prop, array_index) != value_coerce) { - RNA_property_boolean_set_index(ptr, prop, array_index, value_coerce); - written = true; - } + RNA_property_boolean_set_index(ptr, prop, array_index, value_coerce); } else { - if (RNA_property_boolean_get(ptr, prop) != value_coerce) { - RNA_property_boolean_set(ptr, prop, value_coerce); - written = true; - } + RNA_property_boolean_set(ptr, prop, value_coerce); } break; } @@ -1597,16 +1618,10 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val int value_coerce = (int)value; RNA_property_int_clamp(ptr, prop, &value_coerce); if (array_index != -1) { - if (RNA_property_int_get_index(ptr, prop, array_index) != value_coerce) { - RNA_property_int_set_index(ptr, prop, array_index, value_coerce); - written = true; - } + RNA_property_int_set_index(ptr, prop, array_index, value_coerce); } else { - if (RNA_property_int_get(ptr, prop) != value_coerce) { - RNA_property_int_set(ptr, prop, value_coerce); - written = true; - } + RNA_property_int_set(ptr, prop, value_coerce); } break; } @@ -1615,26 +1630,17 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val float value_coerce = value; RNA_property_float_clamp(ptr, prop, &value_coerce); if (array_index != -1) { - if (RNA_property_float_get_index(ptr, prop, array_index) != value_coerce) { - RNA_property_float_set_index(ptr, prop, array_index, value_coerce); - written = true; - } + RNA_property_float_set_index(ptr, prop, array_index, value_coerce); } else { - if (RNA_property_float_get(ptr, prop) != value_coerce) { - RNA_property_float_set(ptr, prop, value_coerce); - written = true; - } + RNA_property_float_set(ptr, prop, value_coerce); } break; } case PROP_ENUM: { const int value_coerce = (int)value; - if (RNA_property_enum_get(ptr, prop) != value_coerce) { - RNA_property_enum_set(ptr, prop, value_coerce); - written = true; - } + RNA_property_enum_set(ptr, prop, value_coerce); break; } default: @@ -1642,54 +1648,17 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val return false; } - /* RNA property update disabled for now - [#28525] [#28690] [#28774] [#28777] */ -#if 0 - /* buffer property update for later flushing */ - if (written && RNA_property_update_check(prop)) { - short skip_updates_hack = 0; - - /* optimization hacks: skip property updates for those properties - * for we know that which the updates in RNA were really just for - * flushing property editing via UI/Py - */ - if (new_ptr.type == &RNA_PoseBone) { - /* bone transforms - update pose (i.e. tag depsgraph) */ - skip_updates_hack = 1; - } - - if (skip_updates_hack == 0) - RNA_property_update_cache_add(ptr, prop); - } -#endif - - /* as long as we don't do property update, we still tag datablock - * as having been updated. this flag does not cause any updates to - * be run, it's for e.g. render engines to synchronize data */ - if (written && ptr->id.data) { - ID *id = ptr->id.data; - - /* for cases like duplifarmes it's only a temporary so don't - * notify anyone of updates */ - if (!(id->recalc & ID_RECALC_SKIP_ANIM_TAG)) { - /* NOTE: This is a bit annoying to use atomic API here, but this - * code is at it's EOL and removed already in 2.8 branch. - */ - atomic_fetch_and_or_int32(&id->recalc, ID_RECALC); - DAG_id_type_tag(G.main, GS(id->name)); - } - } - /* successful */ return true; } /* Simple replacement based data-setting of the FCurve using RNA */ -bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu, float curval) +bool BKE_animsys_execute_fcurve(PointerRNA *ptr, FCurve *fcu, float curval) { PathResolvedRNA anim_rna; bool ok = false; - if (animsys_store_rna_setting(ptr, remap, fcu->rna_path, fcu->array_index, &anim_rna)) { + if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { ok = animsys_write_rna_setting(&anim_rna, curval); } @@ -1697,24 +1666,53 @@ bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu, return ok; } +static void animsys_write_orig_anim_rna( + PointerRNA *ptr, + const char *rna_path, + int array_index, + float value) +{ + /* Pointer is expected to be an ID pointer, if it's not -- we are doomed. + * + * NOTE: It is possible to have animation data on NLA strip, see T57360. + * TODO(sergey): Find solution for those cases. + */ + if (ptr->id.data == NULL) { + return; + } + PointerRNA orig_ptr = *ptr; + orig_ptr.id.data = ((ID *)orig_ptr.id.data)->orig_id; + orig_ptr.data = orig_ptr.id.data; + PathResolvedRNA orig_anim_rna; + /* TODO(sergey): Is there a faster way to get anim_rna of original ID? */ + if (animsys_store_rna_setting(&orig_ptr, rna_path, array_index, &orig_anim_rna)) { + animsys_write_rna_setting(&orig_anim_rna, value); + } +} + /* Evaluate all the F-Curves in the given list * This performs a set of standard checks. If extra checks are required, separate code should be used */ -static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper *remap, float ctime) -{ - FCurve *fcu; - - /* calculate then execute each curve */ - for (fcu = list->first; fcu; fcu = fcu->next) { - /* check if this F-Curve doesn't belong to a muted group */ - 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) { - PathResolvedRNA anim_rna; - if (animsys_store_rna_setting(ptr, remap, fcu->rna_path, fcu->array_index, &anim_rna)) { - const float curval = calculate_fcurve(&anim_rna, fcu, ctime); - animsys_write_rna_setting(&anim_rna, curval); - } +static void animsys_evaluate_fcurves( + Depsgraph *depsgraph, PointerRNA *ptr, ListBase *list, float ctime) +{ + const bool is_active_depsgraph = DEG_is_active(depsgraph); + /* Calculate then execute each curve. */ + for (FCurve *fcu = list->first; fcu; fcu = fcu->next) { + /* Check if this F-Curve doesn't belong to a muted group. */ + if ((fcu->grp != NULL) && (fcu->grp->flag & AGRP_MUTED)) { + continue; + } + /* Check if this curve should be skipped. */ + if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED))) { + continue; + } + PathResolvedRNA anim_rna; + if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { + const float curval = calculate_fcurve(&anim_rna, fcu, ctime); + animsys_write_rna_setting(&anim_rna, curval); + if (is_active_depsgraph) { + animsys_write_orig_anim_rna(ptr, fcu->rna_path, fcu->array_index, curval); } } } @@ -1745,7 +1743,7 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime * new to only be done when drivers only changed */ PathResolvedRNA anim_rna; - if (animsys_store_rna_setting(ptr, NULL, fcu->rna_path, fcu->array_index, &anim_rna)) { + if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, ctime); ok = animsys_write_rna_setting(&anim_rna, curval); } @@ -1798,13 +1796,12 @@ static void action_idcode_patch_check(ID *id, bAction *act) /* ----------------------------------------- */ /* Evaluate Action Group */ -void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *agrp, AnimMapper *remap, float ctime) +void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *agrp, float ctime) { FCurve *fcu; /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */ if (ELEM(NULL, act, agrp)) return; - if ((remap) && (remap->target != act)) remap = NULL; action_idcode_patch_check(ptr->id.data, act); @@ -1817,7 +1814,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * /* check if this curve should be skipped */ if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { PathResolvedRNA anim_rna; - if (animsys_store_rna_setting(ptr, remap, fcu->rna_path, fcu->array_index, &anim_rna)) { + if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, ctime); animsys_write_rna_setting(&anim_rna, curval); } @@ -1826,16 +1823,21 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * } /* Evaluate Action (F-Curve Bag) */ -void animsys_evaluate_action(PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime) +static void animsys_evaluate_action_ex( + Depsgraph *depsgraph, PointerRNA *ptr, bAction *act, float ctime) { /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */ if (act == NULL) return; - if ((remap) && (remap->target != act)) remap = NULL; action_idcode_patch_check(ptr->id.data, act); /* calculate then execute each curve */ - animsys_evaluate_fcurves(ptr, &act->curves, remap, ctime); + animsys_evaluate_fcurves(depsgraph, ptr, &act->curves, ctime); +} + +void animsys_evaluate_action(Depsgraph *depsgraph, PointerRNA *ptr, bAction *act, float ctime) +{ + animsys_evaluate_action_ex(depsgraph, ptr, act, ctime); } /* ***************************************** */ @@ -1864,7 +1866,7 @@ 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) +static void nlastrip_evaluate_controls(Depsgraph *depsgraph, NlaStrip *strip, float ctime) { /* now strip's evaluate F-Curves for these settings (if applicable) */ if (strip->fcurves.first) { @@ -1874,7 +1876,7 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime) RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); /* execute these settings as per normal */ - animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime); + animsys_evaluate_fcurves(depsgraph, &strip_ptr, &strip->fcurves, ctime); } /* analytically generate values for influence and time (if applicable) @@ -1896,7 +1898,7 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime) } /* 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) +NlaEvalStrip *nlastrips_ctime_get_strip(Depsgraph *depsgraph, ListBase *list, ListBase *strips, short index, float ctime) { NlaStrip *strip, *estrip = NULL; NlaEvalStrip *nes; @@ -1973,7 +1975,7 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short * - negative influence is not supported yet... how would that be defined? */ /* TODO: this sounds a bit hacky having a few isolated F-Curves stuck on some data it operates on... */ - nlastrip_evaluate_controls(estrip, ctime); + nlastrip_evaluate_controls(depsgraph, estrip, ctime); if (estrip->influence <= 0.0f) return NULL; @@ -1992,8 +1994,8 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short return NULL; /* evaluate controls for the relevant extents of the bordering strips... */ - nlastrip_evaluate_controls(estrip->prev, estrip->start); - nlastrip_evaluate_controls(estrip->next, estrip->end); + nlastrip_evaluate_controls(depsgraph, estrip->prev, estrip->start); + nlastrip_evaluate_controls(depsgraph, estrip->next, estrip->end); break; } @@ -2016,7 +2018,7 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short /* find an NlaEvalChannel that matches the given criteria * - ptr and prop are the RNA data to find a match for */ -static NlaEvalChannel *nlaevalchan_find_match(ListBase *channels, PointerRNA *ptr, PropertyRNA *prop, int array_index) +static NlaEvalChannel *nlaevalchan_find_match(ListBase *channels, const PathResolvedRNA *prna) { NlaEvalChannel *nec; @@ -2031,7 +2033,7 @@ static NlaEvalChannel *nlaevalchan_find_match(ListBase *channels, PointerRNA *pt * other data stored in PointerRNA cannot allow us to definitively * identify the data */ - if ((nec->ptr.data == ptr->data) && (nec->prop == prop) && (nec->index == array_index)) + if ((nec->rna.ptr.data == prna->ptr.data) && (nec->rna.prop == prna->prop) && ELEM(nec->rna.prop_index, -1, prna->prop_index)) return nec; } @@ -2040,11 +2042,11 @@ static NlaEvalChannel *nlaevalchan_find_match(ListBase *channels, PointerRNA *pt } /* initialise default value for NlaEvalChannel, so that it doesn't blend things wrong */ -static void nlaevalchan_value_init(NlaEvalChannel *nec) +static float nlaevalchan_init_value(PathResolvedRNA *rna) { - PointerRNA *ptr = &nec->ptr; - PropertyRNA *prop = nec->prop; - int index = nec->index; + PointerRNA *ptr = &rna->ptr; + PropertyRNA *prop = rna->prop; + int index = rna->prop_index; /* NOTE: while this doesn't work for all RNA properties as default values aren't in fact * set properly for most of them, at least the common ones (which also happen to get used @@ -2053,61 +2055,43 @@ static void nlaevalchan_value_init(NlaEvalChannel *nec) switch (RNA_property_type(prop)) { case PROP_BOOLEAN: if (RNA_property_array_check(prop)) - nec->value = (float)RNA_property_boolean_get_default_index(ptr, prop, index); + return (float)RNA_property_boolean_get_default_index(ptr, prop, index); else - nec->value = (float)RNA_property_boolean_get_default(ptr, prop); - break; + return (float)RNA_property_boolean_get_default(ptr, prop); case PROP_INT: if (RNA_property_array_check(prop)) - nec->value = (float)RNA_property_int_get_default_index(ptr, prop, index); + return (float)RNA_property_int_get_default_index(ptr, prop, index); else - nec->value = (float)RNA_property_int_get_default(ptr, prop); - break; + return (float)RNA_property_int_get_default(ptr, prop); case PROP_FLOAT: if (RNA_property_array_check(prop)) - nec->value = RNA_property_float_get_default_index(ptr, prop, index); + return RNA_property_float_get_default_index(ptr, prop, index); else - nec->value = RNA_property_float_get_default(ptr, prop); - break; + return RNA_property_float_get_default(ptr, prop); case PROP_ENUM: - nec->value = (float)RNA_property_enum_get_default(ptr, prop); - break; + return (float)RNA_property_enum_get_default(ptr, prop); default: - break; + return 0.0f; } } /* verify that an appropriate NlaEvalChannel for this F-Curve exists */ -static NlaEvalChannel *nlaevalchan_verify(PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes, FCurve *fcu, bool *newChan) +static NlaEvalChannel *nlaevalchan_verify(PointerRNA *ptr, ListBase *channels, FCurve *fcu, bool *newChan) { NlaEvalChannel *nec; - NlaStrip *strip = nes->strip; - PropertyRNA *prop; - PointerRNA new_ptr; - char *path = NULL; - /* short free_path = 0; */ + PathResolvedRNA rna; /* sanity checks */ if (channels == NULL) return NULL; /* get RNA pointer+property info from F-Curve for more convenient handling */ - /* get path, remapped as appropriate to work in its new environment */ - /* free_path = */ /* UNUSED */ animsys_remap_path(strip->remap, fcu->rna_path, &path); - - /* a valid property must be available, and it must be animatable */ - if (RNA_path_resolve_property(ptr, path, &new_ptr, &prop) == false) { - if (G.debug & G_DEBUG) printf("NLA Strip Eval: Cannot resolve path\n"); - return NULL; - } - /* only ok if animatable */ - else if (RNA_property_animateable(&new_ptr, prop) == 0) { - if (G.debug & G_DEBUG) printf("NLA Strip Eval: Property not animatable\n"); + if (!animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &rna)) { return NULL; } /* try to find a match */ - nec = nlaevalchan_find_match(channels, &new_ptr, prop, fcu->array_index); + nec = nlaevalchan_find_match(channels, &rna); /* allocate a new struct for this if none found */ if (nec == NULL) { @@ -2115,12 +2099,13 @@ static NlaEvalChannel *nlaevalchan_verify(PointerRNA *ptr, ListBase *channels, N BLI_addtail(channels, nec); /* store property links for writing to the property later */ - nec->ptr = new_ptr; - nec->prop = prop; - nec->index = fcu->array_index; + nec->rna = rna; + + /* store parameters for use with write_orig_anim_rna */ + nec->rna_path = fcu->rna_path; /* initialise value using default value of property [#35856] */ - nlaevalchan_value_init(nec); + nec->value = nlaevalchan_init_value(&rna); *newChan = true; } else @@ -2199,7 +2184,7 @@ static void nlaevalchan_buffers_accumulate(ListBase *channels, ListBase *tmp_buf necn = nec->next; /* try to find an existing matching channel for this setting in the accumulation buffer */ - necd = nlaevalchan_find_match(channels, &nec->ptr, nec->prop, nec->index); + necd = nlaevalchan_find_match(channels, &nec->rna); /* if there was a matching channel already in the buffer, accumulate to it, * otherwise, add the current channel to the buffer for efficiency @@ -2326,7 +2311,7 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr, ListBase *channels, Li /* get an NLA evaluation channel to work with, and accumulate the evaluated value with the value(s) * stored in this channel if it has been used already */ - nec = nlaevalchan_verify(ptr, channels, nes, fcu, &newChan); + nec = nlaevalchan_verify(ptr, channels, fcu, &newChan); if (nec) nlaevalchan_accumulate(nec, nes, value, newChan); } @@ -2339,7 +2324,8 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr, ListBase *channels, Li } /* evaluate transition strip */ -static void nlastrip_evaluate_transition(PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) +static void nlastrip_evaluate_transition( + Depsgraph *depsgraph, PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { ListBase tmp_channels = {NULL, NULL}; ListBase tmp_modifiers = {NULL, NULL}; @@ -2379,12 +2365,12 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr, ListBase *channels, Li /* first strip */ tmp_nes.strip_mode = NES_TIME_TRANSITION_START; tmp_nes.strip = s1; - nlastrip_evaluate(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); + nlastrip_evaluate(depsgraph, ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); /* second strip */ tmp_nes.strip_mode = NES_TIME_TRANSITION_END; tmp_nes.strip = s2; - nlastrip_evaluate(ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); + nlastrip_evaluate(depsgraph, ptr, &tmp_channels, &tmp_modifiers, &tmp_nes); /* accumulate temp-buffer and full-buffer, using the 'real' strip */ @@ -2395,7 +2381,8 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr, ListBase *channels, Li } /* evaluate meta-strip */ -static void nlastrip_evaluate_meta(PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) +static void nlastrip_evaluate_meta( + Depsgraph *depsgraph, PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { ListBase tmp_modifiers = {NULL, NULL}; NlaStrip *strip = nes->strip; @@ -2415,13 +2402,13 @@ static void nlastrip_evaluate_meta(PointerRNA *ptr, ListBase *channels, ListBase /* 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); + tmp_nes = nlastrips_ctime_get_strip(depsgraph, NULL, &strip->strips, -1, evaltime); /* 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); + nlastrip_evaluate(depsgraph, ptr, channels, &tmp_modifiers, tmp_nes); /* free temp eval-strip */ MEM_freeN(tmp_nes); @@ -2432,7 +2419,7 @@ static void nlastrip_evaluate_meta(PointerRNA *ptr, ListBase *channels, ListBase } /* evaluates the given evaluation strip */ -void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) +void nlastrip_evaluate(Depsgraph *depsgraph, PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes) { NlaStrip *strip = nes->strip; @@ -2450,10 +2437,10 @@ void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, ListBase *modifiers, nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes); break; case NLASTRIP_TYPE_TRANSITION: /* transition */ - nlastrip_evaluate_transition(ptr, channels, modifiers, nes); + nlastrip_evaluate_transition(depsgraph, ptr, channels, modifiers, nes); break; case NLASTRIP_TYPE_META: /* meta */ - nlastrip_evaluate_meta(ptr, channels, modifiers, nes); + nlastrip_evaluate_meta(depsgraph, ptr, channels, modifiers, nes); break; default: /* do nothing */ @@ -2465,7 +2452,7 @@ void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, ListBase *modifiers, } /* write the accumulated settings to */ -void nladata_flush_channels(ListBase *channels) +void nladata_flush_channels(Depsgraph *depsgraph, PointerRNA *ptr, ListBase *channels) { NlaEvalChannel *nec; @@ -2473,39 +2460,13 @@ void nladata_flush_channels(ListBase *channels) if (channels == NULL) return; + const bool is_active_depsgraph = DEG_is_active(depsgraph); + /* for each channel with accumulated values, write its value on the property it affects */ for (nec = channels->first; nec; nec = nec->next) { - PointerRNA *ptr = &nec->ptr; - PropertyRNA *prop = nec->prop; - int array_index = nec->index; - float value = nec->value; - - /* write values - see animsys_write_rna_setting() to sync the code */ - switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: - if (RNA_property_array_check(prop)) - RNA_property_boolean_set_index(ptr, prop, array_index, ANIMSYS_FLOAT_AS_BOOL(value)); - else - RNA_property_boolean_set(ptr, prop, ANIMSYS_FLOAT_AS_BOOL(value)); - break; - case PROP_INT: - if (RNA_property_array_check(prop)) - RNA_property_int_set_index(ptr, prop, array_index, (int)value); - else - RNA_property_int_set(ptr, prop, (int)value); - break; - case PROP_FLOAT: - if (RNA_property_array_check(prop)) - RNA_property_float_set_index(ptr, prop, array_index, value); - else - RNA_property_float_set(ptr, prop, value); - break; - case PROP_ENUM: - RNA_property_enum_set(ptr, prop, (int)value); - break; - default: - /* can't do anything with other types of property.... */ - break; + animsys_write_rna_setting(&nec->rna, nec->value); + if (is_active_depsgraph) { + animsys_write_orig_anim_rna(ptr, nec->rna_path, nec->rna.prop_index, nec->value); } } } @@ -2519,7 +2480,7 @@ void nladata_flush_channels(ListBase *channels) * * \param[out] echannels Evaluation channels with calculated values */ -static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData *adt, float ctime) +static void animsys_evaluate_nla(Depsgraph *depsgraph, ListBase *echannels, PointerRNA *ptr, AnimData *adt, float ctime) { NlaTrack *nlt; short track_index = 0; @@ -2557,7 +2518,7 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData has_strips = true; /* otherwise, get strip to evaluate for this channel */ - nes = nlastrips_ctime_get_strip(&estrips, &nlt->strips, track_index, ctime); + nes = nlastrips_ctime_get_strip(depsgraph, &estrips, &nlt->strips, track_index, ctime); if (nes) nes->track = nlt; } @@ -2582,7 +2543,6 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData else { /* set settings of dummy NLA strip from AnimData settings */ dummy_strip.act = adt->action; - dummy_strip.remap = adt->remap; /* action range is calculated taking F-Modifiers into account (which making new strips doesn't do due to the troublesome nature of that) */ calc_action_range(dummy_strip.act, &dummy_strip.actstart, &dummy_strip.actend, 1); @@ -2598,14 +2558,14 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData } /* add this to our list of evaluation strips */ - nlastrips_ctime_get_strip(&estrips, &dummy_trackslist, -1, ctime); + nlastrips_ctime_get_strip(depsgraph, &estrips, &dummy_trackslist, -1, ctime); } else { /* special case - evaluate as if there isn't any NLA data */ /* TODO: this is really just a stop-gap measure... */ if (G.debug & G_DEBUG) printf("NLA Eval: Stopgap for active action on NLA Stack - no strips case\n"); - animsys_evaluate_action(ptr, adt->action, adt->remap, ctime); + animsys_evaluate_action(depsgraph, ptr, adt->action, ctime); BLI_freelistN(&estrips); return; } @@ -2618,28 +2578,17 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData /* 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); + nlastrip_evaluate(depsgraph, ptr, echannels, NULL, nes); /* 3. free temporary evaluation data that's not used elsewhere */ BLI_freelistN(&estrips); - - /* Tag ID as updated so render engines will recognize changes in data - * which is animated but doesn't have actions. - */ - if (ptr->id.data != NULL) { - ID *id = ptr->id.data; - if (!(id->recalc & ID_RECALC_SKIP_ANIM_TAG)) { - id->recalc |= ID_RECALC; - DAG_id_type_tag(G.main, GS(id->name)); - } - } } /* NLA Evaluation function (mostly for use through do_animdata) * - All channels that will be affected are not cleared anymore. Instead, we just evaluate into * some temp channels, where values can be accumulated in one go. */ -static void animsys_calculate_nla(PointerRNA *ptr, AnimData *adt, float ctime) +static void animsys_calculate_nla(Depsgraph *depsgraph, PointerRNA *ptr, AnimData *adt, float ctime) { ListBase echannels = {NULL, NULL}; @@ -2647,10 +2596,10 @@ static void animsys_calculate_nla(PointerRNA *ptr, AnimData *adt, float ctime) * and also when the user jumps between different times instead of moving sequentially... */ /* evaluate the NLA stack, obtaining a set of values to flush */ - animsys_evaluate_nla(&echannels, ptr, adt, ctime); + animsys_evaluate_nla(depsgraph, &echannels, ptr, adt, ctime); /* flush effects of accumulating channels in NLA to the actual data they affect */ - nladata_flush_channels(&echannels); + nladata_flush_channels(depsgraph, ptr, &echannels); /* free temp data */ BLI_freelistN(&echannels); @@ -2659,19 +2608,6 @@ static void animsys_calculate_nla(PointerRNA *ptr, AnimData *adt, float ctime) /* ***************************************** */ /* Overrides System - Public API */ -/* Clear all overrides */ - -/* Add or get existing Override for given setting */ -#if 0 -AnimOverride *BKE_animsys_validate_override(PointerRNA *UNUSED(ptr), char *UNUSED(path), int UNUSED(array_index)) -{ - /* FIXME: need to define how to get overrides */ - return NULL; -} -#endif - -/* -------------------- */ - /* Evaluate Overrides */ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) { @@ -2680,7 +2616,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) /* for each override, simply execute... */ for (aor = adt->overrides.first; aor; aor = aor->next) { PathResolvedRNA anim_rna; - if (animsys_store_rna_setting(ptr, NULL, aor->rna_path, aor->array_index, &anim_rna)) { + if (animsys_store_rna_setting(ptr, aor->rna_path, aor->array_index, &anim_rna)) { animsys_write_rna_setting(&anim_rna, aor->value); } } @@ -2726,7 +2662,7 @@ 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(Scene *scene, ID *id, AnimData *adt, float ctime, short recalc) +void BKE_animsys_evaluate_animdata(Depsgraph *depsgraph, Scene *scene, ID *id, AnimData *adt, float ctime, short recalc) { PointerRNA id_ptr; @@ -2748,11 +2684,11 @@ void BKE_animsys_evaluate_animdata(Scene *scene, ID *id, AnimData *adt, float ct /* evaluate NLA-stack * - active action is evaluated as part of the NLA stack as the last item */ - animsys_calculate_nla(&id_ptr, adt, ctime); + animsys_calculate_nla(depsgraph, &id_ptr, adt, ctime); } /* evaluate Active Action only */ else if (adt->action) - animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime); + animsys_evaluate_action_ex(depsgraph, &id_ptr, adt->action, ctime); /* reset tag */ adt->recalc &= ~ADT_RECALC_ANIM; @@ -2796,7 +2732,7 @@ void BKE_animsys_evaluate_animdata(Scene *scene, ID *id, AnimData *adt, float ct * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a * standard 'root') block are overridden by a larger 'user' */ -void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) +void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, Scene *scene, float ctime) { ID *id; @@ -2812,7 +2748,7 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) for (id = first; id; id = id->next) { \ if (ID_REAL_USERS(id) > 0) { \ AnimData *adt = BKE_animdata_from_id(id); \ - BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag); \ + BKE_animsys_evaluate_animdata(depsgraph, scene, id, adt, ctime, aflag); \ } \ } (void)0 @@ -2829,9 +2765,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) NtId_Type *ntp = (NtId_Type *)id; \ if (ntp->nodetree) { \ AnimData *adt2 = BKE_animdata_from_id((ID *)ntp->nodetree); \ - BKE_animsys_evaluate_animdata(scene, (ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM); \ + BKE_animsys_evaluate_animdata(depsgraph, scene, (ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM); \ } \ - BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag); \ + BKE_animsys_evaluate_animdata(depsgraph, scene, id, adt, ctime, aflag); \ } \ } (void)0 @@ -2898,6 +2834,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) /* grease pencil */ EVAL_ANIM_IDS(main->gpencil.first, ADT_RECALC_ANIM); + /* palettes */ + EVAL_ANIM_IDS(main->palettes.first, ADT_RECALC_ANIM); + /* cache files */ EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM); @@ -2923,27 +2862,60 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) /* ************** */ /* Evaluation API */ -void BKE_animsys_eval_animdata(EvaluationContext *eval_ctx, ID *id) +void BKE_animsys_eval_animdata(Depsgraph *depsgraph, ID *id) { + float ctime = DEG_get_ctime(depsgraph); AnimData *adt = BKE_animdata_from_id(id); Scene *scene = NULL; /* XXX: this is only needed for flushing RNA updates, * which should get handled as part of the dependency graph instead... */ - DEG_debug_print_eval_time(__func__, id->name, id, eval_ctx->ctime); - BKE_animsys_evaluate_animdata(scene, id, adt, eval_ctx->ctime, ADT_RECALC_ANIM); + DEG_debug_print_eval_time(depsgraph, __func__, id->name, id, ctime); + short recalc = ADT_RECALC_ANIM; + BKE_animsys_evaluate_animdata(depsgraph, scene, id, adt, ctime, recalc); } -void BKE_animsys_eval_driver(EvaluationContext *eval_ctx, +void BKE_animsys_update_driver_array(ID *id) +{ + AnimData *adt = BKE_animdata_from_id(id); + + /* Runtime driver map to avoid O(n^2) lookups in BKE_animsys_eval_driver. + * Ideally the depsgraph could pass a pointer to the COW driver directly, + * but this is difficult in the current design. */ + if (adt && adt->drivers.first) { + BLI_assert(!adt->driver_array); + + int num_drivers = BLI_listbase_count(&adt->drivers); + adt->driver_array = MEM_mallocN(sizeof(FCurve *) * num_drivers, "adt->driver_array"); + + int driver_index = 0; + for (FCurve *fcu = adt->drivers.first; fcu; fcu = fcu->next) { + adt->driver_array[driver_index++] = fcu; + } + } +} + +void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, - FCurve *fcu) + int driver_index, + ChannelDriver *driver_orig) { /* TODO(sergey): De-duplicate with BKE animsys. */ - ChannelDriver *driver = fcu->driver; PointerRNA id_ptr; bool ok = false; + /* Lookup driver, accelerated with driver array map. */ + const AnimData *adt = BKE_animdata_from_id(id); + FCurve *fcu; + + if (adt->driver_array) { + fcu = adt->driver_array[driver_index]; + } + else { + fcu = BLI_findlink(&adt->drivers, driver_index); + } + DEG_debug_print_eval_subdata_index( - __func__, id->name, id, "fcu", fcu->rna_path, fcu, fcu->array_index); + depsgraph, __func__, id->name, id, "fcu", fcu->rna_path, fcu, fcu->array_index); RNA_id_pointer_create(id, &id_ptr); @@ -2951,27 +2923,31 @@ void BKE_animsys_eval_driver(EvaluationContext *eval_ctx, if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { /* check if driver itself is tagged for recalculation */ /* XXX driver recalc flag is not set yet by depsgraph! */ - if ((driver) && !(driver->flag & DRIVER_FLAG_INVALID) /*&& (driver->flag & DRIVER_FLAG_RECALC)*/) { + if ((driver_orig) && !(driver_orig->flag & DRIVER_FLAG_INVALID) /*&& (driver_orig->flag & DRIVER_FLAG_RECALC)*/) { /* 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 */ //printf("\told val = %f\n", fcu->curval); PathResolvedRNA anim_rna; - if (animsys_store_rna_setting(&id_ptr, NULL, fcu->rna_path, fcu->array_index, &anim_rna)) { - const float curval = calculate_fcurve(&anim_rna, fcu, eval_ctx->ctime); + if (animsys_store_rna_setting(&id_ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { + const float ctime = DEG_get_ctime(depsgraph); + const float curval = evaluate_fcurve_driver(&anim_rna, fcu, driver_orig, ctime); ok = animsys_write_rna_setting(&anim_rna, curval); + if (ok && DEG_is_active(depsgraph)) { + animsys_write_orig_anim_rna(&id_ptr, fcu->rna_path, fcu->array_index, curval); + } } //printf("\tnew val = %f\n", fcu->curval); /* clear recalc flag */ - driver->flag &= ~DRIVER_FLAG_RECALC; + driver_orig->flag &= ~DRIVER_FLAG_RECALC; /* set error-flag if evaluation failed */ if (ok == 0) { printf("invalid driver - %s[%d]\n", fcu->rna_path, fcu->array_index); - driver->flag |= DRIVER_FLAG_INVALID; + driver_orig->flag |= DRIVER_FLAG_INVALID; } } } |