diff options
Diffstat (limited to 'source/blender/blenkernel/intern/fcurve.c')
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 270 |
1 files changed, 167 insertions, 103 deletions
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 34357c3e454..972ff377519 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -229,16 +229,13 @@ FCurve *id_data_find_fcurve( return NULL; } - /* Animation takes priority over drivers. */ - if (adt->action && adt->action->curves.first) { - fcu = BKE_fcurve_find(&adt->action->curves, path, index); - } - - /* If not animated, check if driven. */ - if (fcu == NULL && adt->drivers.first) { - fcu = BKE_fcurve_find(&adt->drivers, path, index); - if (fcu && r_driven) { - *r_driven = true; + /* FIXME: The way drivers are handled here (always NULL-ifying `fcu`) is very weird, this needs + * to be re-checked I think?. */ + bool is_driven = false; + fcu = BKE_animadata_fcurve_find_by_rna_path(adt, path, index, NULL, &is_driven); + if (is_driven) { + if (r_driven != NULL) { + *r_driven = is_driven; } fcu = NULL; } @@ -259,12 +256,11 @@ FCurve *BKE_fcurve_find(ListBase *list, const char rna_path[], const int array_i /* Check paths of curves, then array indices... */ for (fcu = list->first; fcu; fcu = fcu->next) { + /* Check indices first, much cheaper than a string comparison. */ /* Simple string-compare (this assumes that they have the same root...) */ - if (fcu->rna_path && STREQ(fcu->rna_path, rna_path)) { - /* Now check indices. */ - if (fcu->array_index == array_index) { - return fcu; - } + if (UNLIKELY(fcu->array_index == array_index && fcu->rna_path && + fcu->rna_path[0] == rna_path[0] && STREQ(fcu->rna_path, rna_path))) { + return fcu; } } @@ -339,6 +335,47 @@ int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, con return matches; } +FCurve *BKE_animadata_fcurve_find_by_rna_path( + AnimData *animdata, const char *rna_path, int rna_index, bAction **r_action, bool *r_driven) +{ + if (r_driven != NULL) { + *r_driven = false; + } + if (r_action != NULL) { + *r_action = NULL; + } + + const bool has_action_fcurves = animdata->action != NULL && + !BLI_listbase_is_empty(&animdata->action->curves); + const bool has_drivers = !BLI_listbase_is_empty(&animdata->drivers); + + /* Animation takes priority over drivers. */ + if (has_action_fcurves) { + FCurve *fcu = BKE_fcurve_find(&animdata->action->curves, rna_path, rna_index); + + if (fcu != NULL) { + if (r_action != NULL) { + *r_action = animdata->action; + } + return fcu; + } + } + + /* If not animated, check if driven. */ + if (has_drivers) { + FCurve *fcu = BKE_fcurve_find(&animdata->drivers, rna_path, rna_index); + + if (fcu != NULL) { + if (r_driven != NULL) { + *r_driven = true; + } + return fcu; + } + } + + return NULL; +} + FCurve *BKE_fcurve_find_by_rna(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, @@ -351,8 +388,8 @@ FCurve *BKE_fcurve_find_by_rna(PointerRNA *ptr, NULL, ptr, prop, rnaindex, r_adt, r_action, r_driven, r_special); } -FCurve *BKE_fcurve_find_by_rna_context_ui(bContext *C, - PointerRNA *ptr, +FCurve *BKE_fcurve_find_by_rna_context_ui(bContext *UNUSED(C), + const PointerRNA *ptr, PropertyRNA *prop, int rnaindex, AnimData **r_animdata, @@ -360,18 +397,18 @@ FCurve *BKE_fcurve_find_by_rna_context_ui(bContext *C, bool *r_driven, bool *r_special) { - FCurve *fcu = NULL; - PointerRNA tptr = *ptr; - - *r_driven = false; - *r_special = false; - - if (r_animdata) { + if (r_animdata != NULL) { *r_animdata = NULL; } - if (r_action) { + if (r_action != NULL) { *r_action = NULL; } + if (r_driven != NULL) { + *r_driven = false; + } + if (r_special) { + *r_special = false; + } /* Special case for NLA Control Curves... */ if (BKE_nlastrip_has_curves_for_property(ptr, prop)) { @@ -380,87 +417,46 @@ FCurve *BKE_fcurve_find_by_rna_context_ui(bContext *C, /* Set the special flag, since it cannot be a normal action/driver * if we've been told to start looking here... */ - *r_special = true; + if (r_special) { + *r_special = true; + } + + *r_driven = false; + if (r_animdata) { + *r_animdata = NULL; + } + if (r_action) { + *r_action = NULL; + } /* The F-Curve either exists or it doesn't here... */ - fcu = BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), rnaindex); - return fcu; + return BKE_fcurve_find(&strip->fcurves, RNA_property_identifier(prop), rnaindex); } /* There must be some RNA-pointer + property combo. */ - if (prop && tptr.owner_id && RNA_property_animateable(&tptr, prop)) { - AnimData *adt = BKE_animdata_from_id(tptr.owner_id); - int step = ( - /* Always 1 in case we have no context (can't check in 'ancestors' of given RNA ptr). */ - C ? 2 : 1); - char *path = NULL; - - if (!adt && C) { - path = RNA_path_from_ID_to_property(&tptr, prop); - adt = BKE_animdata_from_id(tptr.owner_id); - step--; - } - - /* Standard F-Curve - Animation (Action) or Drivers. */ - while (adt && step--) { - if ((adt->action == NULL || adt->action->curves.first == NULL) && - (adt->drivers.first == NULL)) { - continue; - } - - /* XXX This function call can become a performance bottleneck. */ - if (step) { - path = RNA_path_from_ID_to_property(&tptr, prop); - } - if (path == NULL) { - continue; - } - - /* XXX: The logic here is duplicated with a function up above. */ - /* animation takes priority over drivers. */ - if (adt->action && adt->action->curves.first) { - fcu = BKE_fcurve_find(&adt->action->curves, path, rnaindex); - - if (fcu && r_action) { - *r_action = adt->action; - } - } + if (!prop || !ptr->owner_id || !RNA_property_animateable(ptr, prop)) { + return NULL; + } - /* If not animated, check if driven. */ - if (!fcu && (adt->drivers.first)) { - fcu = BKE_fcurve_find(&adt->drivers, path, rnaindex); + AnimData *adt = BKE_animdata_from_id(ptr->owner_id); + if (adt == NULL) { + return NULL; + } - if (fcu) { - if (r_animdata) { - *r_animdata = adt; - } - *r_driven = true; - } - } + /* XXX This function call can become a performance bottleneck. */ + char *rna_path = RNA_path_from_ID_to_property(ptr, prop); + if (rna_path == NULL) { + return NULL; + } - if (fcu && r_action) { - if (r_animdata) { - *r_animdata = adt; - } - *r_action = adt->action; - break; - } + /* Standard F-Curve from animdata - Animation (Action) or Drivers. */ + FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path(adt, rna_path, rnaindex, r_action, r_driven); - if (step) { - char *tpath = path ? path : RNA_path_from_ID_to_property(&tptr, prop); - if (tpath && tpath != path) { - MEM_freeN(path); - path = tpath; - adt = BKE_animdata_from_id(tptr.owner_id); - } - else { - adt = NULL; - } - } - } - MEM_SAFE_FREE(path); + if (fcu != NULL && r_animdata != NULL) { + *r_animdata = adt; } + MEM_freeN(rna_path); return fcu; } @@ -1028,9 +1024,8 @@ static void UNUSED_FUNCTION(bezt_add_to_cfra_elem)(ListBase *lb, BezTriple *bezt * \{ */ /* Some utilities for working with FPoints (i.e. 'sampled' animation curve data, such as - * data imported from BVH/Mocap files), which are specialized for use with high density datasets, - * which BezTriples/Keyframe data are ill equipped to do. - */ + * data imported from BVH/motion-capture files), which are specialized for use with high density + * datasets, which BezTriples/Keyframe data are ill equipped to do. */ float fcurve_samplingcb_evalcurve(FCurve *fcu, void *UNUSED(data), float evaltime) { @@ -1151,7 +1146,7 @@ void fcurve_samples_to_keyframes(FCurve *fcu, const int start, const int end) MEM_SAFE_FREE(fcu->fpt); /* Not strictly needed since we use linear interpolation, but better be consistent here. */ - calchandles_fcurve(fcu); + BKE_fcurve_handles_recalc(fcu); } /* ***************************** F-Curve Sanity ********************************* */ @@ -1221,7 +1216,7 @@ static BezTriple *cycle_offset_triple( return out; } -void calchandles_fcurve_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag) +void BKE_fcurve_handles_recalc_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag) { BezTriple *bezt, *prev, *next; int a = fcu->totvert; @@ -1304,9 +1299,9 @@ void calchandles_fcurve_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag) } } -void calchandles_fcurve(FCurve *fcu) +void BKE_fcurve_handles_recalc(FCurve *fcu) { - calchandles_fcurve_ex(fcu, SELECT); + BKE_fcurve_handles_recalc_ex(fcu, SELECT); } void testhandles_fcurve(FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_handle) @@ -1325,7 +1320,7 @@ void testhandles_fcurve(FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_ha } /* Recalculate handles. */ - calchandles_fcurve_ex(fcu, sel_flag); + BKE_fcurve_handles_recalc_ex(fcu, sel_flag); } void sort_time_fcurve(FCurve *fcu) @@ -1595,6 +1590,12 @@ static void berekeny(float f1, float f2, float f3, float f4, float *o, int b) } } +static void fcurve_bezt_free(FCurve *fcu) +{ + MEM_SAFE_FREE(fcu->bezt); + fcu->totvert = 0; +} + bool BKE_fcurve_bezt_subdivide_handles(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, @@ -1656,6 +1657,69 @@ bool BKE_fcurve_bezt_subdivide_handles(struct BezTriple *bezt, return true; } +void BKE_fcurve_delete_key(FCurve *fcu, int index) +{ + /* sanity check */ + if (fcu == NULL) { + return; + } + + /* verify the index: + * 1) cannot be greater than the number of available keyframes + * 2) negative indices are for specifying a value from the end of the array + */ + if (abs(index) >= fcu->totvert) { + return; + } + if (index < 0) { + index += fcu->totvert; + } + + /* Delete this keyframe */ + memmove( + &fcu->bezt[index], &fcu->bezt[index + 1], sizeof(BezTriple) * (fcu->totvert - index - 1)); + fcu->totvert--; + + /* Free the array of BezTriples if there are not keyframes */ + if (fcu->totvert == 0) { + fcurve_bezt_free(fcu); + } +} + +bool BKE_fcurve_delete_keys_selected(FCurve *fcu) +{ + bool changed = false; + + if (fcu->bezt == NULL) { /* ignore baked curves */ + return false; + } + + /* Delete selected BezTriples */ + for (int i = 0; i < fcu->totvert; i++) { + if (fcu->bezt[i].f2 & SELECT) { + if (i == fcu->active_keyframe_index) { + BKE_fcurve_active_keyframe_set(fcu, NULL); + } + memmove(&fcu->bezt[i], &fcu->bezt[i + 1], sizeof(BezTriple) * (fcu->totvert - i - 1)); + fcu->totvert--; + i--; + changed = true; + } + } + + /* Free the array of BezTriples if there are not keyframes */ + if (fcu->totvert == 0) { + fcurve_bezt_free(fcu); + } + + return changed; +} + +void BKE_fcurve_delete_keys_all(FCurve *fcu) +{ + fcurve_bezt_free(fcu); +} + /** \} */ /* -------------------------------------------------------------------- */ |