forked from bartvdbraak/blender
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.
This commit is contained in:
parent
148985edf0
commit
618b459e8b
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
@ -636,6 +658,10 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie
|
||||
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;
|
||||
}
|
||||
|
||||
/* ********************************************** */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
|
@ -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);
|
||||
|
||||
/* ----------- */
|
||||
|
||||
|
@ -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 **********************************/
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
|
@ -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);
|
||||
|
||||
|
||||
/* **************************************** */
|
||||
|
@ -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 **********************************/
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user