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:
authorCampbell Barton <ideasman42@gmail.com>2010-12-14 18:14:16 +0300
committerCampbell Barton <ideasman42@gmail.com>2010-12-14 18:14:16 +0300
commit78e7c6b329585a0dd6b4d07112d66e54c2a9d5f4 (patch)
tree845c67e5a03a7da21f11bcfcd66d874d52b97fed /source/blender/editors/animation
parent93cbc840e088ca0ecb62f96596d2f7c46e5635ee (diff)
graph editor & action keyframe paste options.
- Offset, so you can paste at the same time of the original frames, at the current frame or relative to the current frame at time of copying. - Merge method, so the pasted keys can overwrite keys in their range or the entire curve. Currently there is no redo panel for these space types so the only way to access these options is with F6 redo popup.
Diffstat (limited to 'source/blender/editors/animation')
-rw-r--r--source/blender/editors/animation/keyframes_general.c121
1 files changed, 108 insertions, 13 deletions
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 3672b3901e4..437f74201e4 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -117,11 +117,18 @@ void delete_fcurve_keys(FCurve *fcu)
}
/* Free the array of BezTriples if there are not keyframes */
- if (fcu->totvert == 0) {
- if (fcu->bezt)
- MEM_freeN(fcu->bezt);
- fcu->bezt= NULL;
- }
+ if(fcu->totvert == 0)
+ clear_fcurve_keys(fcu);
+}
+
+
+void clear_fcurve_keys(FCurve *fcu)
+{
+ if (fcu->bezt)
+ MEM_freeN(fcu->bezt);
+ fcu->bezt= NULL;
+
+ fcu->totvert= 0;
}
/* ---------------- */
@@ -446,6 +453,8 @@ void sample_fcurve (FCurve *fcu)
/* globals for copy/paste data (like for other copy/paste buffers) */
ListBase animcopybuf = {NULL, NULL};
static float animcopy_firstframe= 999999999.0f;
+static float animcopy_lastframe= -999999999.0f;
+static float animcopy_cfra= 0.0;
/* datatype for use in copy/paste buffer */
typedef struct tAnimCopybufItem {
@@ -488,14 +497,16 @@ void free_anim_copybuf (void)
/* restore initial state */
animcopybuf.first= animcopybuf.last= NULL;
animcopy_firstframe= 999999999.0f;
+ animcopy_lastframe= -999999999.0f;
}
/* ------------------- */
/* This function adds data to the keyframes copy/paste buffer, freeing existing data first */
-short copy_animedit_keys (bAnimContext *UNUSED(ac), ListBase *anim_data)
+short copy_animedit_keys (bAnimContext *ac, ListBase *anim_data)
{
bAnimListElem *ale;
+ Scene *scene= ac->scene;
/* clear buffer first */
free_anim_copybuf();
@@ -545,6 +556,8 @@ short copy_animedit_keys (bAnimContext *UNUSED(ac), ListBase *anim_data)
/* check if this is the earliest frame encountered so far */
if (bezt->vec[1][0] < animcopy_firstframe)
animcopy_firstframe= bezt->vec[1][0];
+ if (bezt->vec[1][0] > animcopy_lastframe)
+ animcopy_lastframe= bezt->vec[1][0];
}
}
@@ -553,7 +566,10 @@ short copy_animedit_keys (bAnimContext *UNUSED(ac), ListBase *anim_data)
/* check if anything ended up in the buffer */
if (ELEM(NULL, animcopybuf.first, animcopybuf.last))
return -1;
-
+
+ /* incase 'relative' paste method is used */
+ animcopy_cfra= CFRA;
+
/* everything went fine */
return 0;
}
@@ -636,11 +652,58 @@ static tAnimCopybufItem *pastebuf_match_index_only(FCurve *fcu, const short from
return aci;
}
-static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float offset)
+static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float offset, const eKeyMergeMode merge_mode)
{
BezTriple *bezt;
int i;
+ /* First de-select existing FCuvre */
+ for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ bezt->f2 &= ~SELECT;
+ }
+
+ /* mix mode with existing data */
+ switch(merge_mode) {
+ case KEYFRAME_PASTE_MERGE_MIX:
+ /* do-nothing */
+ break;
+ case KEYFRAME_PASTE_MERGE_OVER:
+ /* remove all keys */
+ clear_fcurve_keys(fcu);
+ break;
+ case KEYFRAME_PASTE_MERGE_OVER_RANGE:
+ case KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL:
+ {
+ float f_min;
+ float f_max;
+
+ if(merge_mode==KEYFRAME_PASTE_MERGE_OVER_RANGE) {
+ f_min= aci->bezt[0].vec[1][0] + offset;
+ f_max= aci->bezt[aci->totvert-1].vec[1][0] + offset;
+ }
+ else { /* Entire Range */
+ f_min= animcopy_firstframe + offset;
+ f_max= animcopy_lastframe + offset;
+ }
+
+ /* remove keys in range */
+
+ if(f_min < f_max) {
+ /* select verts in range for removal */
+ for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if((f_min < bezt[0].vec[1][0]) && (bezt[0].vec[1][0] < f_max)) {
+ bezt->f2 |= SELECT;
+ }
+ }
+
+ /* remove frames in the range */
+ delete_fcurve_keys(fcu);
+ }
+ break;
+ }
+ }
+
+
/* just start pasting, with the the first keyframe on the current frame, and so on */
for (i=0, bezt=aci->bezt; i < aci->totvert; i++, bezt++) {
/* temporarily apply offset to src beztriple while copying */
@@ -663,22 +726,54 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float
calchandles_fcurve(fcu);
}
+EnumPropertyItem keyframe_paste_offset_items[] = {
+ {KEYFRAME_PASTE_OFFSET_CFRA_START, "START", 0, "Frame Start", "Paste keys starting at current frame"},
+ {KEYFRAME_PASTE_OFFSET_CFRA_END, "END", 0, "Frame End", "Paste keys ending at current frame"},
+ {KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE, "RELATIVE", 0, "Frame Relative", "Paste keys relative to the current frame when copying"},
+ {KEYFRAME_PASTE_OFFSET_NONE, "NONE", 0, "No Offset", "Paste keys from original time"},
+ {0, NULL, 0, NULL, NULL}};
+
+EnumPropertyItem keyframe_paste_merge_items[] = {
+ {KEYFRAME_PASTE_MERGE_MIX, "MIX", 0, "Mix", "Overlay existing with new keys"},
+ {KEYFRAME_PASTE_MERGE_OVER, "OVER_ALL", 0, "Overwrite All", "Replace all keys"},
+ {KEYFRAME_PASTE_MERGE_OVER_RANGE, "OVER_RANGE", 0, "Overwrite Range", "Overwrite keys in pasted range"},
+ {KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL, "OVER_RANGE_ALL", 0, "Overwrite Entire Range", "Overwrite keys in pasted range, using the range of all copied keys."},
+ {0, NULL, 0, NULL, NULL}};
+
+
/* This function pastes data from the keyframes copy/paste buffer */
-short paste_animedit_keys (bAnimContext *ac, ListBase *anim_data)
+short paste_animedit_keys (bAnimContext *ac, ListBase *anim_data,
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode)
{
bAnimListElem *ale;
const Scene *scene= (ac->scene);
- const float offset = (float)(CFRA - animcopy_firstframe);
+ float offset;
const short from_single= (animcopybuf.first == animcopybuf.last);
const short to_simple= (anim_data->first == anim_data->last);
int pass;
-
+
/* check if buffer is empty */
if (ELEM(NULL, animcopybuf.first, animcopybuf.last)) {
BKE_report(ac->reports, RPT_WARNING, "No data in buffer to paste");
return -1;
}
+ /* mathods of offset */
+ switch(offset_mode) {
+ case KEYFRAME_PASTE_OFFSET_CFRA_START:
+ offset= (float)(CFRA - animcopy_firstframe);
+ break;
+ case KEYFRAME_PASTE_OFFSET_CFRA_END:
+ offset= (float)(CFRA - animcopy_lastframe);
+ break;
+ case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE:
+ offset= (float)(CFRA - animcopy_cfra);
+ break;
+ case KEYFRAME_PASTE_OFFSET_NONE:
+ offset= 0.0f;
+ break;
+ }
+
if(from_single && to_simple) {
/* 1:1 match, no tricky checking, just paste */
FCurve *fcu;
@@ -688,7 +783,7 @@ short paste_animedit_keys (bAnimContext *ac, ListBase *anim_data)
fcu= (FCurve *)ale->data; /* destination F-Curve */
aci= animcopybuf.first;
- paste_animedit_keys_fcurve(fcu, aci, offset);
+ paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode);
}
else {
/* from selected channels */
@@ -724,7 +819,7 @@ short paste_animedit_keys (bAnimContext *ac, ListBase *anim_data)
/* copy the relevant data from the matching buffer curve */
if (aci) {
totmatch++;
- paste_animedit_keys_fcurve(fcu, aci, offset);
+ paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode);
}
}