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>2010-03-18 16:04:46 +0300
committerJoshua Leung <aligorith@gmail.com>2010-03-18 16:04:46 +0300
commit618b459e8b3630eea747523febec666889a364f7 (patch)
tree481c530e96e9e77ae09029f35a436475921bea39 /source/blender
parent148985edf03814b26f99bf4ae883c83db216ccf3 (diff)
F-Modifier Goodies (as requested by @ndy):
* Copy/Paste operators for F-Modifiers Available in Graph and NLA Editors. Use the Copy/Paste buttons beside the 'Add Modifier' buttons. Copy copies all the modifiers of the ACTIVE F-Curve or Strip depending on the editor. Paste pastes modifiers from the buffer to all the selected F-Curves or Strips, adding the new modifiers to the ends of each list. * 'Stepped Interpolation' F-Modifier This modifier holds each interpolated value from the F-Curve for several frames without changing the timing. This allows to preview motions 'on-twos' for example without altering the timing, or having to go through setting heaps of keyframes. In this case, Andy wanted to use this for CG <-> StopMo.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h1
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c69
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c108
-rw-r--r--source/blender/editors/include/ED_anim_api.h19
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c7
-rw-r--r--source/blender/editors/space_graph/graph_edit.c117
-rw-r--r--source/blender/editors/space_graph/graph_intern.h2
-rw-r--r--source/blender/editors/space_graph/graph_ops.c3
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c5
-rw-r--r--source/blender/editors/space_nla/nla_edit.c124
-rw-r--r--source/blender/editors/space_nla/nla_intern.h2
-rw-r--r--source/blender/editors/space_nla/nla_ops.c2
-rw-r--r--source/blender/makesdna/DNA_anim_types.h9
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c26
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c2
16 files changed, 490 insertions, 7 deletions
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 9df6bfdbe7c..c4d74f86284 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -158,6 +158,7 @@ FModifierTypeInfo *get_fmodifier_typeinfo(int type);
/* ---------------------- */
struct FModifier *add_fmodifier(ListBase *modifiers, int type);
+struct FModifier *copy_fmodifier(struct FModifier *src);
void copy_fmodifiers(ListBase *dst, ListBase *src);
int remove_fmodifier(ListBase *modifiers, struct FModifier *fcm);
int remove_fmodifier_index(ListBase *modifiers, int index);
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index bbef3227490..02f35bb78f8 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -871,6 +871,49 @@ static FModifierTypeInfo FMI_LIMITS = {
fcm_limits_evaluate /* evaluate */
};
+/* Stepped F-Curve Modifier --------------------------- */
+
+static void fcm_stepped_new_data (void *mdata)
+{
+ FMod_Stepped *data= (FMod_Stepped *)mdata;
+
+ /* just need to set the step-size to 2-frames by default */
+ // XXX: or would 5 be more normal?
+ data->step_size = 2.0f;
+}
+
+static float fcm_stepped_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime)
+{
+ FMod_Stepped *data= (FMod_Stepped *)fcm->data;
+ int snapblock;
+
+ /* we snap to the start of the previous closest block of 'step_size' frames
+ * after the start offset has been discarded
+ * - i.e. round down
+ */
+ snapblock = (int)((evaltime - data->start) / data->step_size);
+
+ /* reapply the offset, and multiple the snapblock by the size of the steps to get
+ * the new time to evaluate at
+ */
+ return ((float)snapblock * data->step_size) + data->start;
+}
+
+static FModifierTypeInfo FMI_STEPPED = {
+ FMODIFIER_TYPE_STEPPED, /* type */
+ sizeof(FMod_Limits), /* size */
+ FMI_TYPE_GENERATE_CURVE, /* action type */ /* XXX... err... */
+ FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
+ "Stepped", /* name */
+ "FMod_Stepped", /* struct name */
+ NULL, /* free data */
+ NULL, /* copy data */
+ fcm_stepped_new_data, /* new data */
+ NULL, /* verify */
+ fcm_stepped_time, /* evaluate time */
+ NULL /* evaluate */
+};
+
/* F-Curve Modifier API --------------------------- */
/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out
* and operations that involve F-Curve modifier specific code.
@@ -892,6 +935,7 @@ static void fmods_init_typeinfo ()
fmodifiersTypeInfo[6]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented
fmodifiersTypeInfo[7]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */
fmodifiersTypeInfo[8]= &FMI_LIMITS; /* Limits F-Curve Modifier */
+ fmodifiersTypeInfo[9]= &FMI_STEPPED; /* Stepped F-Curve Modifier */
}
/* This function should be used for getting the appropriate type-info when only
@@ -968,6 +1012,31 @@ FModifier *add_fmodifier (ListBase *modifiers, int type)
return fcm;
}
+/* Make a copy of the specified F-Modifier */
+FModifier *copy_fmodifier (FModifier *src)
+{
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(src);
+ FModifier *dst;
+
+ /* sanity check */
+ if (src == NULL)
+ return NULL;
+
+ /* copy the base data, clearing the links */
+ dst = MEM_dupallocN(src);
+ dst->next = dst->prev = NULL;
+
+ /* make a new copy of the F-Modifier's data */
+ dst->data = MEM_dupallocN(src->data);
+
+ /* only do specific constraints if required */
+ if (fmi && fmi->copy_data)
+ fmi->copy_data(dst, src);
+
+ /* return the new modifier */
+ return dst;
+}
+
/* Duplicate all of the F-Modifiers in the Modifier stacks */
void copy_fmodifiers (ListBase *dst, ListBase *src)
{
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 9d0fe99976b..22bb5317383 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -30,6 +30,9 @@
* This file defines the (C-Coded) templates + editing callbacks needed
* by the interface stuff or F-Modifiers, as used by F-Curves in the Graph Editor,
* and NLA-Strips in the NLA Editor.
+ *
+ * Copy/Paste Buffer for F-Modifiers:
+ * For now, this is also defined in this file so that it can be shared between the
*/
#include <string.h>
@@ -47,15 +50,18 @@
#include "RNA_access.h"
+#include "ED_anim_api.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
+/* ********************************************** */
+/* UI STUFF */
+
// XXX! --------------------------------
/* temporary definition for limits of float number buttons (FLT_MAX tends to infinity with old system) */
#define UI_FLT_MAX 10000.0f
-/* ********************************************** */
-
#define B_REDR 1
#define B_FMODIFIER_REDRAW 20
@@ -549,6 +555,22 @@ static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, shor
/* --------------- */
+/* draw settings for stepped interpolation modifier */
+static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, short width)
+{
+ uiLayout *col;
+ PointerRNA ptr;
+
+ /* init the RNA-pointer */
+ RNA_pointer_create(id, &RNA_FModifierStepped, fcm, &ptr);
+
+ col= uiLayoutColumn(layout, 0);
+
+ uiItemR(col, NULL, 0, &ptr, "step_size", 0);
+ uiItemR(col, NULL, 0, &ptr, "start_offset", 0);
+}
+
+/* --------------- */
void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm)
{
@@ -635,6 +657,10 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie
case FMODIFIER_TYPE_NOISE: /* Noise */
draw_modifier__noise(box, id, fcm, width);
break;
+
+ case FMODIFIER_TYPE_STEPPED: /* Stepped */
+ draw_modifier__stepped(box, id, fcm, width);
+ break;
default: /* unknown type */
break;
@@ -643,3 +669,81 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie
}
/* ********************************************** */
+/* COPY/PASTE BUFFER STUFF */
+
+/* Copy/Paste Buffer itself (list of FModifier 's) */
+static ListBase fmodifier_copypaste_buf = {NULL, NULL};
+
+/* ---------- */
+
+/* free the copy/paste buffer */
+void free_fmodifiers_copybuf (void)
+{
+ /* just free the whole buffer */
+ free_fmodifiers(&fmodifier_copypaste_buf);
+}
+
+/* copy the given F-Modifiers to the buffer, returning whether anything was copied or not
+ * assuming that the buffer has been cleared already with free_fmodifiers_copybuf()
+ * - active: only copy the active modifier
+ */
+short ANIM_fmodifiers_copy_to_buf (ListBase *modifiers, short active)
+{
+ short ok = 1;
+
+ /* sanity checks */
+ if ELEM(NULL, modifiers, modifiers->first)
+ return 0;
+
+ /* copy the whole list, or just the active one? */
+ if (active) {
+ FModifier *fcm = find_active_fmodifier(modifiers);
+
+ if (fcm) {
+ FModifier *fcmN = copy_fmodifier(fcm);
+ BLI_addtail(&fmodifier_copypaste_buf, fcmN);
+ }
+ else
+ ok = 0;
+ }
+ else
+ copy_fmodifiers(&fmodifier_copypaste_buf, modifiers);
+
+ /* did we succeed? */
+ return ok;
+}
+
+/* 'Paste' the F-Modifier(s) from the buffer to the specified list
+ * - replace: free all the existing modifiers to leave only the pasted ones
+ */
+short ANIM_fmodifiers_paste_from_buf (ListBase *modifiers, short replace)
+{
+ FModifier *fcm;
+ short ok = 0;
+
+ /* sanity checks */
+ if (modifiers == NULL)
+ return 0;
+
+ /* if replacing the list, free the existing modifiers */
+ if (replace)
+ free_fmodifiers(modifiers);
+
+ /* now copy over all the modifiers in the buffer to the end of the list */
+ for (fcm= fmodifier_copypaste_buf.first; fcm; fcm= fcm->next) {
+ /* make a copy of it */
+ FModifier *fcmN = copy_fmodifier(fcm);
+
+ /* make sure the new one isn't active, otherwise the list may get several actives */
+ fcmN->flag &= ~FMODIFIER_FLAG_ACTIVE;
+
+ /* now add it to the end of the list */
+ BLI_addtail(modifiers, fcmN);
+ ok = 1;
+ }
+
+ /* did we succeed? */
+ return ok;
+}
+
+/* ********************************************** */
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 2f089a41a3f..3892770c1f4 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -452,9 +452,28 @@ void ANIM_draw_previewrange(const struct bContext *C, struct View2D *v2d);
/* ************************************************* */
/* F-MODIFIER TOOLS */
+/* ------------- UI Panel Drawing -------------- */
+
/* draw a given F-Modifier for some layout/UI-Block */
void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout, struct ID *id, ListBase *modifiers, struct FModifier *fcm);
+/* ------------- Copy/Paste Buffer -------------- */
+
+
+/* free the copy/paste buffer */
+void free_fmodifiers_copybuf(void);
+
+/* copy the given F-Modifiers to the buffer, returning whether anything was copied or not
+ * assuming that the buffer has been cleared already with free_fmodifiers_copybuf()
+ * - active: only copy the active modifier
+ */
+short ANIM_fmodifiers_copy_to_buf(ListBase *modifiers, short active);
+
+/* 'Paste' the F-Modifier(s) from the buffer to the specified list
+ * - replace: free all the existing modifiers to leave only the pasted ones
+ */
+short ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, short replace);
+
/* ************************************************* */
/* ASSORTED TOOLS */
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 3975c88fe5c..78fd2e06683 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -610,8 +610,13 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa)
row= uiLayoutRow(pa->layout, 0);
block= uiLayoutGetBlock(row);
- // XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
+ // XXX for now, this will be a operator button which calls a 'add modifier' operator
uiDefButO(block, BUT, "GRAPH_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 0, 150, 20, "Adds a new F-Curve Modifier for the active F-Curve");
+
+ /* copy/paste (as sub-row)*/
+ row= uiLayoutRow(row, 1);
+ uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_fmodifier_copy");
+ uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_fmodifier_paste");
}
/* draw each modifier */
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 485c9ab8bf4..d23bafbc001 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -1971,7 +1971,7 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
filter |= (ANIMFILTER_SEL|ANIMFILTER_CURVEVISIBLE);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
- /* smooth keyframes */
+ /* add f-modifier to each curve */
for (ale= anim_data.first; ale; ale= ale->next) {
FCurve *fcu= (FCurve *)ale->data;
FModifier *fcm;
@@ -2017,4 +2017,119 @@ void GRAPH_OT_fmodifier_add (wmOperatorType *ot)
RNA_def_boolean(ot->srna, "only_active", 1, "Only Active", "Only add F-Modifier to active F-Curve.");
}
+/* ******************** Copy F-Modifiers Operator *********************** */
+
+static int graph_fmodifier_copy_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ bAnimListElem *ale;
+ short ok = 0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* clear buffer first */
+ free_fmodifiers_copybuf();
+
+ /* get the active F-Curve */
+ ale= get_active_fcurve_channel(&ac);
+
+ /* if this exists, call the copy F-Modifiers API function */
+ if (ale && ale->data) {
+ FCurve *fcu= (FCurve *)ale->data;
+
+ // TODO: when 'active' vs 'all' boolean is added, change last param!
+ ok= ANIM_fmodifiers_copy_to_buf(&fcu->modifiers, 0);
+
+ /* free temp data now */
+ MEM_freeN(ale);
+ }
+
+ /* successful or not? */
+ if (ok == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
+ return OPERATOR_CANCELLED;
+ }
+ else
+ return OPERATOR_FINISHED;
+}
+
+void GRAPH_OT_fmodifier_copy (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Copy F-Modifiers";
+ ot->idname= "GRAPH_OT_fmodifier_copy";
+ ot->description= "Copy the F-Modifier(s) of the active F-Curve.";
+
+ /* api callbacks */
+ ot->exec= graph_fmodifier_copy_exec;
+ ot->poll= graphop_active_fcurve_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ //ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All F-Modifiers", "Copy all the F-Modifiers, instead of just the active one");
+}
+
+/* ******************** Paste F-Modifiers Operator *********************** */
+
+static int graph_fmodifier_paste_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter, ok=0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* filter data */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* paste modifiers */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu= (FCurve *)ale->data;
+
+ // TODO: do we want to replace existing modifiers? add user pref for that!
+ ok += ANIM_fmodifiers_paste_from_buf(&fcu->modifiers, 0);
+ }
+
+ /* clean up */
+ BLI_freelistN(&anim_data);
+
+ /* successful or not? */
+ if (ok) {
+ /* validate keyframes after editing */
+ ANIM_editkeyframes_refresh(&ac);
+
+ /* set notifier that keyframes have changed */
+ WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void GRAPH_OT_fmodifier_paste (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Paste F-Modifiers";
+ ot->idname= "GRAPH_OT_fmodifier_paste";
+ ot->description= "Add copied F-Modifiers to the selected F-Curves";
+
+ /* api callbacks */
+ ot->exec= graph_fmodifier_paste_exec;
+ ot->poll= graphop_editable_keyframes_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
/* ************************************************************************** */
diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h
index 696d31e22e1..356cd05b509 100644
--- a/source/blender/editors/space_graph/graph_intern.h
+++ b/source/blender/editors/space_graph/graph_intern.h
@@ -139,6 +139,8 @@ enum {
/* ----------- */
void GRAPH_OT_fmodifier_add(struct wmOperatorType *ot);
+void GRAPH_OT_fmodifier_copy(struct wmOperatorType *ot);
+void GRAPH_OT_fmodifier_paste(struct wmOperatorType *ot);
/* ----------- */
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 7c1ac14027a..63c877e7402 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -262,8 +262,9 @@ void graphedit_operatortypes(void)
WM_operatortype_append(GRAPH_OT_click_insert);
/* F-Curve Modifiers */
- // XXX temporary?
WM_operatortype_append(GRAPH_OT_fmodifier_add);
+ WM_operatortype_append(GRAPH_OT_fmodifier_copy);
+ WM_operatortype_append(GRAPH_OT_fmodifier_paste);
}
/* ************************** registration - keymaps **********************************/
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 4f944d1b855..944a93a713f 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -430,6 +430,11 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa)
// XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
// FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected)
uiDefButO(block, BUT, "NLA_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 0, 150, 20, "Adds a new F-Modifier for the active NLA Strip");
+
+ /* copy/paste (as sub-row)*/
+ row= uiLayoutRow(row, 1);
+ uiItemO(row, "", ICON_COPYDOWN, "NLA_OT_fmodifier_copy");
+ uiItemO(row, "", ICON_PASTEDOWN, "NLA_OT_fmodifier_paste");
}
/* draw each modifier */
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 543fa1dfed7..bc99ded4db6 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -1633,8 +1633,7 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
BLI_freelistN(&anim_data);
/* set notifier that things have changed */
- // FIXME: this doesn't really do it justice...
- WM_event_add_notifier(C, NC_ANIMATION, NULL);
+ WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
/* done */
return OPERATOR_FINISHED;
@@ -1659,4 +1658,125 @@ void NLA_OT_fmodifier_add (wmOperatorType *ot)
RNA_def_boolean(ot->srna, "only_active", 0, "Only Active", "Only add F-Modifier of the specified type to the active strip.");
}
+/* ******************** Copy F-Modifiers Operator *********************** */
+
+static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter, ok=0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* clear buffer first */
+ free_fmodifiers_copybuf();
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each NLA-Track, add the specified modifier to all selected strips */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ for (strip= nlt->strips.first; strip; strip=strip->next) {
+ /* only add F-Modifier if on active strip? */
+ if ((strip->flag & NLASTRIP_FLAG_ACTIVE)==0)
+ continue;
+
+ // TODO: when 'active' vs 'all' boolean is added, change last param!
+ ok += ANIM_fmodifiers_copy_to_buf(&strip->modifiers, 0);
+ }
+ }
+
+ /* successful or not? */
+ if (ok == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
+ return OPERATOR_CANCELLED;
+ }
+ else
+ return OPERATOR_FINISHED;
+}
+
+void NLA_OT_fmodifier_copy (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Copy F-Modifiers";
+ ot->idname= "NLA_OT_fmodifier_copy";
+ ot->description= "Copy the F-Modifier(s) of the active NLA-Strip.";
+
+ /* api callbacks */
+ ot->exec= nla_fmodifier_copy_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* id-props */
+ //ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All F-Modifiers", "Copy all the F-Modifiers, instead of just the active one");
+}
+
+/* ******************** Paste F-Modifiers Operator *********************** */
+
+static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter, ok=0;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get a list of the editable tracks being shown in the NLA */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_SEL | ANIMFILTER_FOREDIT);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* for each NLA-Track, add the specified modifier to all selected strips */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ NlaTrack *nlt= (NlaTrack *)ale->data;
+ NlaStrip *strip;
+
+ for (strip= nlt->strips.first; strip; strip=strip->next) {
+ // TODO: do we want to replace existing modifiers? add user pref for that!
+ ok += ANIM_fmodifiers_paste_from_buf(&strip->modifiers, 0);
+ }
+ }
+
+ /* clean up */
+ BLI_freelistN(&anim_data);
+
+ /* successful or not? */
+ if (ok) {
+ /* set notifier that things have changed */
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_EDIT, NULL);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void NLA_OT_fmodifier_paste (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Paste F-Modifiers";
+ ot->idname= "NLA_OT_fmodifier_paste";
+ ot->description= "Add copied F-Modifiers to the selected NLA-Strips";
+
+ /* api callbacks */
+ ot->exec= nla_fmodifier_paste_exec;
+ ot->poll= nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
/* *********************************************** */
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
index 1af2d2a1635..18ef91220f9 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -111,6 +111,8 @@ void NLA_OT_clear_scale(wmOperatorType *ot);
void NLA_OT_snap(wmOperatorType *ot);
void NLA_OT_fmodifier_add(wmOperatorType *ot);
+void NLA_OT_fmodifier_copy(wmOperatorType *ot);
+void NLA_OT_fmodifier_paste(wmOperatorType *ot);
/* **************************************** */
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index 10ff10f46fd..249256a47f9 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -165,6 +165,8 @@ void nla_operatortypes(void)
WM_operatortype_append(NLA_OT_snap);
WM_operatortype_append(NLA_OT_fmodifier_add);
+ WM_operatortype_append(NLA_OT_fmodifier_copy);
+ WM_operatortype_append(NLA_OT_fmodifier_paste);
}
/* ************************** registration - keymaps **********************************/
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 8e46cfefba5..44727218f4f 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -73,6 +73,7 @@ typedef enum eFModifier_Types {
FMODIFIER_TYPE_FILTER, /* unimplemented - for applying: fft, high/low pass filters, etc. */
FMODIFIER_TYPE_PYTHON,
FMODIFIER_TYPE_LIMITS,
+ FMODIFIER_TYPE_STEPPED,
/* NOTE: all new modifiers must be added above this line */
FMODIFIER_NUM_TYPES
@@ -211,6 +212,7 @@ typedef enum eFMod_Limit_Flags {
FCM_LIMIT_YMAX = (1<<3),
} eFMod_Limit_Flags;
+
/* noise modifier data */
typedef struct FMod_Noise {
float size;
@@ -230,6 +232,13 @@ typedef enum eFMod_Noise_Modifications {
FCM_NOISE_MODIF_MULTIPLY, /* Multiply the curve by noise */
} eFMod_Noise_Modifications;
+
+/* stepped modifier data */
+typedef struct FMod_Stepped {
+ float step_size; /* Number of frames each interpolated value should be held */
+ float start; /* Reference frame number that stepping starts from */
+} FMod_Stepped;
+
/* Drivers -------------------------------------- */
/* Driver Target (dtar)
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index e50b1b7ad58..2671f480d3b 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -217,6 +217,7 @@ extern StructRNA RNA_FModifierGenerator;
extern StructRNA RNA_FModifierLimits;
extern StructRNA RNA_FModifierNoise;
extern StructRNA RNA_FModifierPython;
+extern StructRNA RNA_FModifierStepped;
extern StructRNA RNA_FollowPathConstraint;
extern StructRNA RNA_Function;
extern StructRNA RNA_GameBooleanProperty;
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index d5d28ac83ae..3ab4673212d 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -51,6 +51,7 @@ EnumPropertyItem fmodifier_type_items[] = {
{FMODIFIER_TYPE_FILTER, "FILTER", 0, "Filter", ""},
{FMODIFIER_TYPE_PYTHON, "PYTHON", 0, "Python", ""},
{FMODIFIER_TYPE_LIMITS, "LIMITS", 0, "Limits", ""},
+ {FMODIFIER_TYPE_STEPPED, "STEPPED", 0, "Stepped Interpolation", ""},
{0, NULL, 0, NULL, NULL}};
EnumPropertyItem beztriple_keyframe_type_items[] = {
@@ -84,6 +85,8 @@ static StructRNA *rna_FModifierType_refine(struct PointerRNA *ptr)
return &RNA_FModifierPython;
case FMODIFIER_TYPE_LIMITS:
return &RNA_FModifierLimits;
+ case FMODIFIER_TYPE_STEPPED:
+ return &RNA_FModifierStepped;
default:
return &RNA_UnknownType;
}
@@ -712,9 +715,31 @@ static void rna_def_fmodifier_noise(BlenderRNA *brna)
}
+/* --------- */
+
+static void rna_def_fmodifier_stepped(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna= RNA_def_struct(brna, "FModifierStepped", "FModifier");
+ RNA_def_struct_ui_text(srna, "Stepped Interpolation F-Modifier", "Holds each interpolated value from the F-Curve for several frames without changing the timing");
+ RNA_def_struct_sdna_from(srna, "FMod_Stepped", "data");
+
+ /* properties */
+ prop= RNA_def_property(srna, "step_size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Step Size", "Number of frames to hold each value");
+ RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
+
+ prop= RNA_def_property(srna, "start_offset", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "start");
+ RNA_def_property_ui_text(prop, "Start Offset", "Reference number of frames before frames get held. Use to get hold for '1-3' vs '5-7' holding patterns");
+ RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
+}
/* --------- */
+
static void rna_def_fmodifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1209,6 +1234,7 @@ void RNA_def_fcurve(BlenderRNA *brna)
rna_def_fmodifier_python(brna);
rna_def_fmodifier_limits(brna);
rna_def_fmodifier_noise(brna);
+ rna_def_fmodifier_stepped(brna);
}
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index ae310a7f59d..e5b5e0db1b4 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -217,6 +217,7 @@ extern wchar_t *copybufinfo;
// XXX copy/paste buffer stuff...
extern void free_anim_copybuf();
extern void free_anim_drivers_copybuf();
+extern void free_fmodifiers_copybuf();
extern void free_posebuf();
/* called in creator.c even... tsk, split this! */
@@ -272,6 +273,7 @@ void WM_exit(bContext *C)
// free_matcopybuf();
free_anim_copybuf();
free_anim_drivers_copybuf();
+ free_fmodifiers_copybuf();
free_posebuf();
// free_vertexpaint();
// free_imagepaint();