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:
-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[];