diff options
-rw-r--r-- | source/blender/blenkernel/intern/fmodifier.c | 61 | ||||
-rw-r--r-- | source/blender/editors/animation/fmodifier_ui.c | 26 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_anim_types.h | 6 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_fcurve.c | 34 |
4 files changed, 117 insertions, 10 deletions
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index 4a1a0f9ac6b..dcf81c19479 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -1013,6 +1013,7 @@ FModifier *add_fmodifier (ListBase *modifiers, int type) fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier"); fcm->type = type; fcm->flag = FMODIFIER_FLAG_EXPANDED; + fcm->influence = 1.0f; BLI_addtail(modifiers, fcm); /* tag modifier as "active" if no other modifiers exist in the stack yet */ @@ -1200,6 +1201,47 @@ short list_has_suitable_fmodifier (ListBase *modifiers, int mtype, short acttype /* Evaluation API --------------------------- */ +/* helper function - calculate influence of FModifier */ +static float eval_fmodifier_influence (FModifier *fcm, float evaltime) +{ + float influence; + + /* sanity check */ + if (fcm == NULL) + return 0.0f; + + /* should we use influence stored in modifier or not + * NOTE: this is really just a hack so that we don't need to version patch old files ;) + */ + if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE) + influence = fcm->influence; + else + influence = 1.0f; + + /* restricted range or full range? */ + if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) { + if ((evaltime <= fcm->sfra) || (evaltime >= fcm->efra)) { + /* out of range */ + return 0.0f; + } + else if ((evaltime > fcm->sfra) && (evaltime < fcm->sfra + fcm->blendin)) { + /* blend in range */ + float a = fcm->sfra; + float b = fcm->sfra + fcm->blendin; + return influence * (evaltime - a) / (b - a); + } + else if ((evaltime < fcm->efra) && (evaltime > fcm->efra - fcm->blendout)) { + /* blend out range */ + float a = fcm->efra; + float b = fcm->efra - fcm->blendout; + return influence * (evaltime - a) / (b - a); + } + } + + /* just return the influence of the modifier */ + return influence; +} + /* evaluate time modifications imposed by some F-Curve Modifiers * - this step acts as an optimisation to prevent the F-Curve stack being evaluated * several times by modifiers requesting the time be modified, as the final result @@ -1240,10 +1282,13 @@ float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime)) ) { /* only evaluate if there's a callback for this */ - // TODO: implement the 'influence' control feature... if (fmi->evaluate_modifier_time) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) { + float influence = eval_fmodifier_influence(fcm, evaltime); + float nval = fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); + + evaltime = interpf(nval, evaltime, influence); + } } } } @@ -1271,13 +1316,17 @@ void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, continue; /* only evaluate if there's a callback for this, and if F-Modifier can be evaluated on this frame */ - // TODO: implement the 'influence' control feature... if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT)==0 || ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime)) ) { if (fmi->evaluate_modifier) { - if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) - fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime); + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) { + float influence = eval_fmodifier_influence(fcm, evaltime); + float nval = *cvalue; + + fmi->evaluate_modifier(fcu, fcm, &nval, evaltime); + *cvalue = interpf(nval, *cvalue, influence); + } } } } diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index 3018fa697b8..8058454f510 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -604,7 +604,7 @@ static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, sho void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm) { FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); - uiLayout *box, *row, *subrow; + uiLayout *box, *row, *subrow, *col; uiBlock *block; uiBut *but; short width= 314; @@ -700,16 +700,36 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie { box = uiLayoutBox(layout); + /* restricted range ----------------------------------------------------- */ + col = uiLayoutColumn(box, 1); + /* top row: use restricted range */ - row= uiLayoutRow(box, 0); + row= uiLayoutRow(col, 1); uiItemR(row, &ptr, "use_restricted_range", 0, NULL, ICON_NONE); if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) { /* second row: settings */ - row = uiLayoutRow(box, 1); + row = uiLayoutRow(col, 1); uiItemR(row, &ptr, "frame_start", 0, "Start", ICON_NONE); uiItemR(row, &ptr, "frame_end", 0, "End", ICON_NONE); + + /* third row: blending influence */ + row = uiLayoutRow(col, 1); + + uiItemR(row, &ptr, "blend_in", 0, "In", ICON_NONE); + uiItemR(row, &ptr, "blend_out", 0, "Out", ICON_NONE); + } + + /* influence -------------------------------------------------------------- */ + col = uiLayoutColumn(box, 1); + + /* top row: use influence */ + uiItemR(col, &ptr, "use_influence", 0, NULL, ICON_NONE); + + if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE) { + /* second row: influence value */ + uiItemR(col, &ptr, "influence", 0, NULL, ICON_NONE); } } } diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 88a3fe81825..c650d15722d 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -65,6 +65,8 @@ typedef struct FModifier { float sfra; /* start frame of restricted frame-range */ float efra; /* end frame of restricted frame-range */ + float blendin; /* number of frames from sfra before modifier takes full influence */ + float blendout; /* number of frames from efra before modifier fades out */ } FModifier; /* Types of F-Curve modifier @@ -97,7 +99,9 @@ typedef enum eFModifier_Flags { /* user wants modifier to be skipped */ FMODIFIER_FLAG_MUTED = (1<<3), /* restrict range that F-Modifier can be considered over */ - FMODIFIER_FLAG_RANGERESTRICT = (1<<4) + FMODIFIER_FLAG_RANGERESTRICT = (1<<4), + /* use influence control */ + FMODIFIER_FLAG_USEINFLUENCE = (1<<5) } eFModifier_Flags; /* --- */ diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index ba0563f554a..263978221bb 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -470,6 +470,14 @@ static void rna_FModifier_end_frame_range(PointerRNA *ptr, float *min, float *ma *max= MAXFRAMEF; } +static void rna_FModifier_blending_range(PointerRNA *ptr, float *min, float *max) +{ + FModifier *fcm= (FModifier*)ptr->data; + + *min= 0.0f; + *max= fcm->efra - fcm->sfra; +} + static void rna_FModifier_active_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { FModifier *fm, *fmo= (FModifier*)ptr->data; @@ -1050,6 +1058,32 @@ static void rna_def_fmodifier(BlenderRNA *brna) RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_end_frame_range"); RNA_def_property_ui_text(prop, "End Frame", "Frame that modifier's influence ends (if Restrict Frame Range is in use)"); RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); + + prop= RNA_def_property(srna, "blend_in", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "blendin"); + RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_blending_range"); + RNA_def_property_ui_text(prop, "Blend In", "Number of frames from start frame for influence to take effect"); + RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); + + prop= RNA_def_property(srna, "blend_out", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "blendout"); + RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_blending_range"); + RNA_def_property_ui_text(prop, "Blend Out", "Number of frames from start frame for influence to fade out"); + RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); + + /* influence */ + prop= RNA_def_property(srna, "use_influence", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_USEINFLUENCE); + RNA_def_property_ui_text(prop, "Use Influence", "F-Curve Modifier's effects will be tempered by a default factor"); + RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); + RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1); // XXX: depends on UI implementation + + prop= RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "influence"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Influence", "Amount of influence F-Curve Modifier will have when not fading in/out"); + RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL); } /* *********************** */ |