diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2016-08-09 17:37:15 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2016-08-09 17:37:15 +0300 |
commit | 4a801f6c6f0421ffd515c12422dd197441440520 (patch) | |
tree | 5415e844b460bb2aa07b9467c72e13abc2e61228 /source/blender/blenkernel/intern/anim_sys.c | |
parent | 49c63d46db8c055152d9e431e89405f9b51a4bbe (diff) | |
parent | 02719521d2e25abcc8ffcccc086d3a651986f52f (diff) |
Merge branch 'master' into object_nodesobject_nodes
Diffstat (limited to 'source/blender/blenkernel/intern/anim_sys.c')
-rw-r--r-- | source/blender/blenkernel/intern/anim_sys.c | 343 |
1 files changed, 202 insertions, 141 deletions
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index d04b950c043..1a5d77bbc07 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -97,6 +97,7 @@ bool id_type_can_have_animdata(const short id_type) case ID_MC: case ID_MSK: case ID_GD: + case ID_CF: return true; /* no AnimData */ @@ -1160,6 +1161,9 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u /* grease pencil */ ANIMDATA_IDS_CB(mainptr->gpencil.first); + + /* cache files */ + ANIMDATA_IDS_CB(mainptr->cachefiles.first); } /* Fix all RNA-Paths throughout the database (directly access the Global.main version) @@ -1250,6 +1254,9 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const cha /* grease pencil */ RENAMEFIX_ANIM_IDS(mainptr->gpencil.first); + + /* cache files */ + RENAMEFIX_ANIM_IDS(mainptr->cachefiles.first); /* scenes */ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene); @@ -1482,161 +1489,193 @@ static bool animsys_remap_path(AnimMapper *UNUSED(remap), char *path, char **dst return false; } +static bool animsys_store_rna_setting( + PointerRNA *ptr, AnimMapper *remap, + /* 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); + + /* write value to setting */ + if (path) { + /* get property to write to */ + if (RNA_path_resolve_property(ptr, path, &r_result->ptr, &r_result->prop)) { + if ((ptr->id.data == NULL) || RNA_property_animateable(&r_result->ptr, r_result->prop)) { + int array_len = RNA_property_array_length(&r_result->ptr, r_result->prop); + + if (array_len && array_index >= array_len) { + if (G.debug & G_DEBUG) { + printf("Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d\n", + (ptr && ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", + path, array_index, array_len - 1); + } + } + else { + r_result->prop_index = array_len ? array_index : -1; + success = true; + } + } + } + else { + /* failed to get path */ + /* XXX don't tag as failed yet though, as there are some legit situations (Action Constraint) + * where some channels will not exist, but shouldn't lock up Action */ + if (G.debug & G_DEBUG) { + printf("Animato: Invalid path. ID = '%s', '%s[%d]'\n", + (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", + path, array_index); + } + } + } + + /* free temp path-info */ + if (free_path) { + MEM_freeN((void *)path); + } + + return success; +} + /* less than 1.0 evaluates to false, use epsilon to avoid float error */ #define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON))) /* Write the given value to a setting using RNA, and return success */ -static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_index, float value) +static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float value) { - PropertyRNA *prop; - PointerRNA new_ptr; + PropertyRNA *prop = anim_rna->prop; + PointerRNA *ptr = &anim_rna->ptr; + int array_index = anim_rna->prop_index; - //printf("%p %s %i %f\n", ptr, path, array_index, value); - - /* get property to write to */ - if (RNA_path_resolve_property(ptr, path, &new_ptr, &prop)) { - /* 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! - */ - if (RNA_property_animateable(&new_ptr, prop) || (ptr->id.data == NULL)) { - int array_len = RNA_property_array_length(&new_ptr, prop); - bool written = false; - - if (array_len && array_index >= array_len) { - if (G.debug & G_DEBUG) { - printf("Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d\n", - (ptr && ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", - path, array_index, array_len - 1); + /* 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; + + 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; } - - return false; } - - switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: - if (array_len) { - if (RNA_property_boolean_get_index(&new_ptr, prop, array_index) != ANIMSYS_FLOAT_AS_BOOL(value)) { - RNA_property_boolean_set_index(&new_ptr, prop, array_index, ANIMSYS_FLOAT_AS_BOOL(value)); - written = true; - } - } - else { - if (RNA_property_boolean_get(&new_ptr, prop) != ANIMSYS_FLOAT_AS_BOOL(value)) { - RNA_property_boolean_set(&new_ptr, prop, ANIMSYS_FLOAT_AS_BOOL(value)); - written = true; - } - } - break; - case PROP_INT: - if (array_len) { - if (RNA_property_int_get_index(&new_ptr, prop, array_index) != (int)value) { - RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value); - written = true; - } - } - else { - if (RNA_property_int_get(&new_ptr, prop) != (int)value) { - RNA_property_int_set(&new_ptr, prop, (int)value); - written = true; - } - } - break; - case PROP_FLOAT: - if (array_len) { - if (RNA_property_float_get_index(&new_ptr, prop, array_index) != value) { - RNA_property_float_set_index(&new_ptr, prop, array_index, value); - written = true; - } - } - else { - if (RNA_property_float_get(&new_ptr, prop) != value) { - RNA_property_float_set(&new_ptr, prop, value); - written = true; - } - } - break; - case PROP_ENUM: - if (RNA_property_enum_get(&new_ptr, prop) != (int)value) { - RNA_property_enum_set(&new_ptr, prop, (int)value); - written = true; - } - break; - default: - /* nothing can be done here... so it is unsuccessful? */ - return false; + else { + if (RNA_property_boolean_get(ptr, prop) != value_coerce) { + RNA_property_boolean_set(ptr, prop, value_coerce); + written = true; + } } - - /* 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; + break; + } + case PROP_INT: + { + const int value_coerce = (int)value; + 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; } - - if (skip_updates_hack == 0) - RNA_property_update_cache_add(&new_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 && new_ptr.id.data) { - ID *id = new_ptr.id.data; - - /* for cases like duplifarmes it's only a temporary so don't - * notify anyone of updates */ - if (!(id->tag & LIB_TAG_ANIM_NO_RECALC)) { - id->tag |= LIB_TAG_ID_RECALC; - DAG_id_type_tag(G.main, GS(id->name)); + else { + if (RNA_property_int_get(ptr, prop) != value_coerce) { + RNA_property_int_set(ptr, prop, value_coerce); + written = true; } } + break; } - - /* successful */ - return true; + case PROP_FLOAT: + { + if (array_index != -1) { + if (RNA_property_float_get_index(ptr, prop, array_index) != value) { + RNA_property_float_set_index(ptr, prop, array_index, value); + written = true; + } + } + else { + if (RNA_property_float_get(ptr, prop) != value) { + RNA_property_float_set(ptr, prop, value); + written = true; + } + } + 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; + } + break; + } + default: + /* nothing can be done here... so it is unsuccessful? */ + return false; } - else { - /* failed to get path */ - /* XXX don't tag as failed yet though, as there are some legit situations (Action Constraint) - * where some channels will not exist, but shouldn't lock up Action */ - if (G.debug & G_DEBUG) { - printf("Animato: Invalid path. ID = '%s', '%s[%d]'\n", - (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", - path, array_index); + + /* 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->tag & LIB_TAG_ANIM_NO_RECALC)) { + id->tag |= LIB_TAG_ID_RECALC; + DAG_id_type_tag(G.main, GS(id->name)); } - return false; } + + /* 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) { - char *path = NULL; - bool free_path = false; + PathResolvedRNA anim_rna; bool ok = false; - - /* get path, remapped as appropriate to work in its new environment */ - free_path = animsys_remap_path(remap, fcu->rna_path, &path); - - /* write value to setting */ - if (path) - ok = animsys_write_rna_setting(ptr, path, fcu->array_index, curval); - - /* free temp path-info */ - if (free_path) - MEM_freeN(path); - + + if (animsys_store_rna_setting(ptr, remap, fcu->rna_path, fcu->array_index, &anim_rna)) { + ok = animsys_write_rna_setting(&anim_rna, curval); + } + /* return whether we were successful */ return ok; } @@ -1654,8 +1693,11 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper if ((fcu->grp == NULL) || (fcu->grp->flag & AGRP_MUTED) == 0) { /* check if this curve should be skipped */ if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { - const float curval = calculate_fcurve(fcu, ctime); - BKE_animsys_execute_fcurve(ptr, remap, fcu, curval); + 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); + } } } } @@ -1684,8 +1726,12 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime /* evaluate this using values set already in other places * NOTE: for 'layering' option later on, we should check if we should remove old value before adding * new to only be done when drivers only changed */ - const float curval = calculate_fcurve(fcu, ctime); - ok = BKE_animsys_execute_fcurve(ptr, NULL, fcu, curval); + + PathResolvedRNA anim_rna; + if (animsys_store_rna_setting(ptr, NULL, 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); + } /* clear recalc flag */ driver->flag &= ~DRIVER_FLAG_RECALC; @@ -1753,8 +1799,11 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * for (fcu = agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu = fcu->next) { /* check if this curve should be skipped */ if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { - const float curval = calculate_fcurve(fcu, ctime); - BKE_animsys_execute_fcurve(ptr, remap, fcu, curval); + 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); + } } } } @@ -2612,8 +2661,12 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) AnimOverride *aor; /* for each override, simply execute... */ - for (aor = adt->overrides.first; aor; aor = aor->next) - animsys_write_rna_setting(ptr, aor->rna_path, aor->array_index, aor->value); + 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)) { + animsys_write_rna_setting(&anim_rna, aor->value); + } + } } /* ***************************************** */ @@ -2827,6 +2880,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) /* grease pencil */ EVAL_ANIM_IDS(main->gpencil.first, ADT_RECALC_ANIM); + + /* cache files */ + EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM); /* objects */ /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets @@ -2888,8 +2944,13 @@ void BKE_animsys_eval_driver(EvaluationContext *eval_ctx, * NOTE: for 'layering' option later on, we should check if we should remove old value before adding * new to only be done when drivers only changed */ //printf("\told val = %f\n", fcu->curval); - const float curval = calculate_fcurve(fcu, eval_ctx->ctime); - ok = BKE_animsys_execute_fcurve(&id_ptr, NULL, 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); + ok = animsys_write_rna_setting(&anim_rna, curval); + } + //printf("\tnew val = %f\n", fcu->curval); /* clear recalc flag */ |