Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2009-09-04 08:27:06 +0400
committerJoshua Leung <aligorith@gmail.com>2009-09-04 08:27:06 +0400
commita819ef1bf2222b2e1132c0a3d9b6b133c8263348 (patch)
tree0302e8fef8f5db846429df8b07c56f2fdd50d738 /source/blender/editors/animation
parentd577e0d986651ee28c6c1031df7db966430f218f (diff)
2.5 - Keyframing Bugfixes + Code Cleanups
* DopeSheet + Graph Editor - 'Sample Keyframes' option now tags newly created keyframes as being breakdowns. Also moved reduced the code duplication here by moving the core code for this to the animation module. * Keyframing (Standard/Auto) - Added proper 'replace' option Keyframes can now be rekeyed non-destructively when the INSERTKEY_REPLACE flag is provided to the keyframing API functions, since this option will make sure that only the values of the handles get altered. For the Auto-Keyframing 'Replace/Edit Keys' option, this means that it truly works as it describes now, since it will now only replace the values of the keyframes on the current frame, and won't create new keyframes in the process or destroy the tangents already created for those keys. For things like the sliders in animation editors, keyframes changing the value won't destroy existing tangents.
Diffstat (limited to 'source/blender/editors/animation')
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c6
-rw-r--r--source/blender/editors/animation/keyframes_general.c76
-rw-r--r--source/blender/editors/animation/keyframing.c90
-rw-r--r--source/blender/editors/animation/keyingsets.c3
4 files changed, 144 insertions, 31 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index b16420a7094..e3418fa194f 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -2003,6 +2003,8 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
flag |= INSERTKEY_NEEDED;
if (IS_AUTOKEY_FLAG(AUTOMATKEY))
flag |= INSERTKEY_MATRIX;
+ if (IS_AUTOKEY_MODE(scene, EDITKEYS))
+ flag |= INSERTKEY_REPLACE;
/* get RNA pointer, and resolve the path */
@@ -2010,6 +2012,10 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
/* try to resolve the path stored in the F-Curve */
if (RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop)) {
+ /* set the special 'replace' flag if on a keyframe */
+ if (fcurve_frame_has_keyframe(fcu, cfra, 0))
+ flag |= INSERTKEY_REPLACE;
+
/* insert a keyframe for this F-Curve */
done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index ced3c117700..f13d35c7d4a 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -357,6 +357,76 @@ void smooth_fcurve (FCurve *fcu)
calchandles_fcurve(fcu);
}
+/* ---------------- */
+
+/* little cache for values... */
+typedef struct tempFrameValCache {
+ float frame, val;
+} tempFrameValCache;
+
+
+/* Evaluates the curves between each selected keyframe on each frame, and keys the value */
+void sample_fcurve (FCurve *fcu)
+{
+ BezTriple *bezt, *start=NULL, *end=NULL;
+ tempFrameValCache *value_cache, *fp;
+ int sfra, range;
+ int i, n, nIndex;
+
+ /* find selected keyframes... once pair has been found, add keyframes */
+ for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ /* check if selected, and which end this is */
+ if (BEZSELECTED(bezt)) {
+ if (start) {
+ /* set end */
+ end= bezt;
+
+ /* cache values then add keyframes using these values, as adding
+ * keyframes while sampling will affect the outcome...
+ * - only start sampling+adding from index=1, so that we don't overwrite original keyframe
+ */
+ range= (int)( ceil(end->vec[1][0] - start->vec[1][0]) );
+ sfra= (int)( floor(start->vec[1][0]) );
+
+ if (range) {
+ value_cache= MEM_callocN(sizeof(tempFrameValCache)*range, "IcuFrameValCache");
+
+ /* sample values */
+ for (n=1, fp=value_cache; n<range && fp; n++, fp++) {
+ fp->frame= (float)(sfra + n);
+ fp->val= evaluate_fcurve(fcu, fp->frame);
+ }
+
+ /* add keyframes with these, tagging as 'breakdowns' */
+ for (n=1, fp=value_cache; n<range && fp; n++, fp++) {
+ nIndex= insert_vert_fcurve(fcu, fp->frame, fp->val, 1);
+ BEZKEYTYPE(fcu->bezt + nIndex)= BEZT_KEYTYPE_BREAKDOWN;
+ }
+
+ /* free temp cache */
+ MEM_freeN(value_cache);
+
+ /* as we added keyframes, we need to compensate so that bezt is at the right place */
+ bezt = fcu->bezt + i + range - 1;
+ i += (range - 1);
+ }
+
+ /* bezt was selected, so it now marks the start of a whole new chain to search */
+ start= bezt;
+ end= NULL;
+ }
+ else {
+ /* just set start keyframe */
+ start= bezt;
+ end= NULL;
+ }
+ }
+ }
+
+ /* recalculate channel's handles? */
+ calchandles_fcurve(fcu);
+}
+
/* **************************************************** */
/* Copy/Paste Tools */
/* - The copy/paste buffer currently stores a set of temporary F-Curves containing only the keyframes
@@ -529,8 +599,10 @@ short paste_animedit_keys (bAnimContext *ac, ListBase *anim_data)
bezt->vec[1][0] += offset;
bezt->vec[2][0] += offset;
- /* insert the keyframe */
- insert_bezt_fcurve(fcu, bezt);
+ /* insert the keyframe
+ * NOTE: no special flags here for now
+ */
+ insert_bezt_fcurve(fcu, bezt, 0);
/* un-apply offset from src beztriple after copying */
bezt->vec[0][0] -= offset;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 5f444609baa..d731ec6f148 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -262,9 +262,8 @@ static int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen
* NOTE: any recalculate of the F-Curve that needs to be done will need to
* be done by the caller.
*/
-int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt)
+int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt, short flag)
{
- BezTriple *newb;
int i= 0;
if (fcu->bezt) {
@@ -273,13 +272,34 @@ int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt)
if (replace) {
/* sanity check: 'i' may in rare cases exceed arraylen */
- // FIXME: do not overwrite handletype if just replacing...?
- if ((i >= 0) && (i < fcu->totvert))
- *(fcu->bezt + i) = *bezt;
+ if ((i >= 0) && (i < fcu->totvert)) {
+ /* take care with the handletypes and other info if the replacement flags are set */
+ if (flag & INSERTKEY_REPLACE) {
+ BezTriple *dst= (fcu->bezt + i);
+ float dy= bezt->vec[1][1] - dst->vec[1][1];
+
+ /* just apply delta value change to the handle values */
+ dst->vec[0][1] += dy;
+ dst->vec[1][1] += dy;
+ dst->vec[2][1] += dy;
+
+ // TODO: perform some other operations?
+ }
+ else {
+ /* just brutally replace the values */
+ *(fcu->bezt + i) = *bezt;
+ }
+ }
}
- else {
- /* add new */
- newb= MEM_callocN((fcu->totvert+1)*sizeof(BezTriple), "beztriple");
+ else if ((flag & INSERTKEY_REPLACE) == 0) {
+ /* add new - if we're not restricted to replacing keyframes only */
+ BezTriple *newb;
+
+ /* allocate a new array only if we have to */
+ if ((flag & INSERTKEY_FASTR) == 0)
+ newb= MEM_callocN((fcu->totvert+1)*sizeof(BezTriple), "beztriple");
+ else
+ newb= fcu->bezt;
/* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */
if (i > 0)
@@ -292,9 +312,11 @@ int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt)
if (i < fcu->totvert)
memcpy(newb+i+1, fcu->bezt+i, (fcu->totvert-i)*sizeof(BezTriple));
- /* replace (+ free) old with new */
- MEM_freeN(fcu->bezt);
- fcu->bezt= newb;
+ /* replace (+ free) old with new, only if necessary to do so */
+ if ((flag & INSERTKEY_FASTR) == 0) {
+ MEM_freeN(fcu->bezt);
+ fcu->bezt= newb;
+ }
fcu->totvert++;
}
@@ -313,13 +335,11 @@ int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt)
return i;
}
-/* This function is a wrapper for insert_bezt_icu, and should be used when
- * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere
- * else yet.
- *
- * 'fast' - is only for the python API where importing BVH's would take an extreamly long time.
+/* This function is a wrapper for insert_bezt_fcurve_internal(), and should be used when
+ * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere else yet.
+ * It returns the index at which the keyframe was added.
*/
-void insert_vert_fcurve (FCurve *fcu, float x, float y, short fast)
+int insert_vert_fcurve (FCurve *fcu, float x, float y, short flag)
{
BezTriple beztr;
int a;
@@ -337,21 +357,22 @@ void insert_vert_fcurve (FCurve *fcu, float x, float y, short fast)
beztr.h1= beztr.h2= HD_AUTO; // XXX what about when we replace an old one?
/* add temp beztriple to keyframes */
- a= insert_bezt_fcurve(fcu, &beztr);
+ a= insert_bezt_fcurve(fcu, &beztr, flag);
/* what if 'a' is a negative index?
* for now, just exit to prevent any segfaults
*/
- if (a < 0) return;
+ if (a < 0) return -1;
/* don't recalculate handles if fast is set
* - this is a hack to make importers faster
- * - we may calculate twice (see editipo_changed(), due to autohandle needing two calculations)
+ * - we may calculate twice (due to autohandle needing to be calculated twice)
*/
- if (!fast) calchandles_fcurve(fcu);
+ if ((flag & INSERTKEY_FAST) == 0)
+ calchandles_fcurve(fcu);
/* set handletype and interpolation */
- if (fcu->totvert > 2) {
+ if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE)==0) {
BezTriple *bezt= (fcu->bezt + a);
char h1, h2;
@@ -370,10 +391,14 @@ void insert_vert_fcurve (FCurve *fcu, float x, float y, short fast)
/* don't recalculate handles if fast is set
* - this is a hack to make importers faster
- * - we may calculate twice (see editipo_changed(), due to autohandle needing two calculations)
+ * - we may calculate twice (due to autohandle needing to be calculated twice)
*/
- if (!fast) calchandles_fcurve(fcu);
+ if ((flag & INSERTKEY_FAST) == 0)
+ calchandles_fcurve(fcu);
}
+
+ /* return the index at which the keyframe was added */
+ return a;
}
/* -------------- 'Smarter' Keyframing Functions -------------------- */
@@ -812,7 +837,7 @@ short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, fl
/* insert new keyframe at current frame */
if (insert_mode)
- insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
+ insert_vert_fcurve(fcu, cfra, curval, flag);
/* delete keyframe immediately before/after newly added */
switch (insert_mode) {
@@ -830,7 +855,7 @@ short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, fl
}
else {
/* just insert keyframe */
- insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
+ insert_vert_fcurve(fcu, cfra, curval, flag);
/* return success */
return 1;
@@ -1303,6 +1328,15 @@ static int insert_key_button_exec (bContext *C, wmOperator *op)
float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
short success= 0;
int a, index, length, all= RNA_boolean_get(op->ptr, "all");
+ short flag = 0;
+
+ /* flags for inserting keyframes */
+ if (IS_AUTOKEY_FLAG(AUTOMATKEY))
+ flag |= INSERTKEY_MATRIX;
+ if (IS_AUTOKEY_FLAG(INSERTNEEDED))
+ flag |= INSERTKEY_NEEDED;
+ if (IS_AUTOKEY_MODE(scene, EDITKEYS))
+ flag |= INSERTKEY_REPLACE;
/* try to insert keyframe using property retrieved from UI */
memset(&ptr, 0, sizeof(PointerRNA));
@@ -1322,14 +1356,14 @@ static int insert_key_button_exec (bContext *C, wmOperator *op)
length= 1;
for (a=0; a<length; a++)
- success+= insert_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, 0);
+ success+= insert_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, flag);
MEM_freeN(path);
}
else if (ptr.type == &RNA_NlaStrip) {
/* handle special vars for NLA-strips */
NlaStrip *strip= (NlaStrip *)ptr.data;
- FCurve *fcu= list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
+ FCurve *fcu= list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag);
success+= insert_keyframe_direct(ptr, prop, fcu, cfra, 0);
}
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 21f969467aa..f81f57d526a 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -879,6 +879,7 @@ short modifykey_get_context_data (bContext *C, ListBase *dsources, KeyingSet *ks
*/
int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
{
+ Scene *scene= CTX_data_scene(C);
KS_Path *ksp;
int kflag=0, success= 0;
char *groupname= NULL;
@@ -891,7 +892,7 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *
/* suppliment with info from the context */
if (IS_AUTOKEY_FLAG(AUTOMATKEY)) kflag |= INSERTKEY_MATRIX;
if (IS_AUTOKEY_FLAG(INSERTNEEDED)) kflag |= INSERTKEY_NEEDED;
- // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
+ if (IS_AUTOKEY_MODE(scene, EDITKEYS)) kflag |= INSERTKEY_REPLACE;
}
else if (mode == MODIFYKEY_MODE_DELETE)
kflag= 0;