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
path: root/source
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
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')
-rw-r--r--source/blender/editors/animation/keyframes_general.c121
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h27
-rw-r--r--source/blender/editors/space_action/action_edit.c14
-rw-r--r--source/blender/editors/space_graph/graph_edit.c14
-rw-r--r--source/blender/makesrna/RNA_enum_types.h3
5 files changed, 159 insertions, 20 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);
}
}
diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h
index 5ea9287a71e..2a7ce9b540b 100644
--- a/source/blender/editors/include/ED_keyframes_edit.h
+++ b/source/blender/editors/include/ED_keyframes_edit.h
@@ -152,6 +152,29 @@ typedef struct KeyframeEditCD_Remap {
float newMin, newMax; /* new range */
} KeyframeEditCD_Remap;
+/* Paste options */
+typedef enum eKeyPasteOffset {
+ /* paste keys starting at current frame */
+ KEYFRAME_PASTE_OFFSET_CFRA_START,
+ /* paste keys ending at current frame */
+ KEYFRAME_PASTE_OFFSET_CFRA_END,
+ /* paste keys relative to the current frame when copying */
+ KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE,
+ /* paste keys from original time */
+ KEYFRAME_PASTE_OFFSET_NONE
+} eKeyPasteOffset;
+
+typedef enum eKeyMergeMode {
+ /* overlay existing with new keys */
+ KEYFRAME_PASTE_MERGE_MIX,
+ /* replace entire fcurve */
+ KEYFRAME_PASTE_MERGE_OVER,
+ /* overwrite keys in pasted range */
+ KEYFRAME_PASTE_MERGE_OVER_RANGE,
+ /* overwrite keys in pasted range (use all keyframe start & end for range) */
+ KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL
+} eKeyMergeMode;
+
/* ---------------- Looping API --------------------- */
/* functions for looping over keyframes */
@@ -212,6 +235,7 @@ void bezt_remap_times(KeyframeEditData *ked, struct BezTriple *bezt);
void delete_fcurve_key(struct FCurve *fcu, int index, short do_recalc);
void delete_fcurve_keys(struct FCurve *fcu);
+void clear_fcurve_keys(struct FCurve *fcu);
void duplicate_fcurve_keys(struct FCurve *fcu);
void clean_fcurve(struct FCurve *fcu, float thresh);
@@ -222,7 +246,8 @@ void sample_fcurve(struct FCurve *fcu);
void free_anim_copybuf(void);
short copy_animedit_keys(struct bAnimContext *ac, ListBase *anim_data);
-short paste_animedit_keys(struct bAnimContext *ac, ListBase *anim_data);
+short paste_animedit_keys(struct bAnimContext *ac, ListBase *anim_data,
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode);
/* ************************************************ */
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 59e4cfcf68f..afda04d1c45 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -291,7 +291,8 @@ static short copy_action_keys (bAnimContext *ac)
}
-static short paste_action_keys (bAnimContext *ac)
+static short paste_action_keys (bAnimContext *ac,
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode)
{
ListBase anim_data = {NULL, NULL};
int filter, ok=0;
@@ -301,7 +302,7 @@ static short paste_action_keys (bAnimContext *ac)
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* paste keyframes */
- ok= paste_animedit_keys(ac, &anim_data);
+ ok= paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode);
/* clean up */
BLI_freelistN(&anim_data);
@@ -341,11 +342,15 @@ void ACTION_OT_copy (wmOperatorType *ot)
ot->description= "Copy selected keyframes to the copy/paste buffer";
/* api callbacks */
+// ot->invoke= WM_operator_props_popup; // better wait for graph redo panel
ot->exec= actkeys_copy_exec;
ot->poll= ED_operator_action_active;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "offset", keyframe_paste_offset_items, KEYFRAME_PASTE_OFFSET_CFRA_START, "Offset", "Paste time offset of keys");
+ RNA_def_enum(ot->srna, "merge", keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merking pasted keys and existing");
}
@@ -353,6 +358,9 @@ void ACTION_OT_copy (wmOperatorType *ot)
static int actkeys_paste_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+
+ const eKeyPasteOffset offset_mode= RNA_enum_get(op->ptr, "offset");
+ const eKeyMergeMode merge_mode= RNA_enum_get(op->ptr, "merge");
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -367,7 +375,7 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
// FIXME...
}
else {
- if (paste_action_keys(&ac)) {
+ if (paste_action_keys(&ac, offset_mode, merge_mode)) {
BKE_report(op->reports, RPT_ERROR, "No keyframes to paste");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 798e1b12242..1e6443bba32 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -618,7 +618,8 @@ static short copy_graph_keys (bAnimContext *ac)
return ok;
}
-static short paste_graph_keys (bAnimContext *ac)
+static short paste_graph_keys (bAnimContext *ac,
+ const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode)
{
ListBase anim_data = {NULL, NULL};
int filter, ok=0;
@@ -628,7 +629,7 @@ static short paste_graph_keys (bAnimContext *ac)
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* paste keyframes */
- ok= paste_animedit_keys(ac, &anim_data);
+ ok= paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode);
/* clean up */
BLI_freelistN(&anim_data);
@@ -676,6 +677,9 @@ void GRAPH_OT_copy (wmOperatorType *ot)
static int graphkeys_paste_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+
+ const eKeyPasteOffset offset_mode= RNA_enum_get(op->ptr, "offset");
+ const eKeyMergeMode merge_mode= RNA_enum_get(op->ptr, "merge");
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -686,7 +690,7 @@ static int graphkeys_paste_exec(bContext *C, wmOperator *op)
}
/* paste keyframes */
- if (paste_graph_keys(&ac)) {
+ if (paste_graph_keys(&ac, offset_mode, merge_mode)) {
return OPERATOR_CANCELLED;
}
@@ -707,11 +711,15 @@ void GRAPH_OT_paste (wmOperatorType *ot)
ot->description= "Paste keyframes from copy/paste buffer for the selected channels, starting on the current frame";
/* api callbacks */
+// ot->invoke= WM_operator_props_popup; // better wait for graph redo panel
ot->exec= graphkeys_paste_exec;
ot->poll= graphop_editable_keyframes_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "offset", keyframe_paste_offset_items, KEYFRAME_PASTE_OFFSET_CFRA_START, "Offset", "Paste time offset of keys");
+ RNA_def_enum(ot->srna, "merge", keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merking pasted keys and existing");
}
/* ******************** Duplicate Keyframes Operator ************************* */
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 9b6b12ef727..8e5463d5990 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -57,6 +57,9 @@ extern EnumPropertyItem beztriple_interpolation_mode_items[];
extern EnumPropertyItem keyingset_path_grouping_items[];
+extern EnumPropertyItem keyframe_paste_offset_items[];
+extern EnumPropertyItem keyframe_paste_merge_items[];
+
extern EnumPropertyItem fmodifier_type_items[];
extern EnumPropertyItem nla_mode_extend_items[];