forked from bartvdbraak/blender
More F-Modifier Tweaks:
This commit started out aiming to make the "Stepped" F-Modifier (committed last night) even more useful, but ended up fixing a few other finer-points of how F-Modifiers work. Firstly, the new stuff: I've addded options to the Stepped F-Modifier to not affect frames before and/or after specified values, and renamed the 'start offset' to 'offset' for clarity. The main objective of this is to allow Stepped F-Modifiers to only affect certain time ranges, so that by layering/using multiple instances of the F-Modifier, it can be possible to have multiple stepping-sizes. This allows for effects like: http://www.pasteall.org/blend/2230 or in words, it provides a convenient mechanism for animators to specify whether sections of the animation is shown "on twos", "fours", or even "forty-second-ths plus a smidgen", as can be easily done with 2D. Assorted changes to support this: * Properly fixed up how F-Modifiers that work with time, evaluate the time to evaluate the curve at. Now layered time effects like this should be possible in a much nicer way. * Added proper value range validation/clamping to many properties. There are still a lot more that need checking, but at least more properties now do "the right thing".
This commit is contained in:
parent
5e7b1bde8d
commit
d89a8c34f3
@ -887,16 +887,26 @@ static float fcm_stepped_time (FCurve *fcu, FModifier *fcm, float cvalue, float
|
||||
FMod_Stepped *data= (FMod_Stepped *)fcm->data;
|
||||
int snapblock;
|
||||
|
||||
/* check range clamping to see if we should alter the timing to achieve the desired results */
|
||||
if (data->flag & FCM_STEPPED_NO_BEFORE) {
|
||||
if (evaltime < data->start_frame)
|
||||
return evaltime;
|
||||
}
|
||||
if (data->flag & FCM_STEPPED_NO_AFTER) {
|
||||
if (evaltime > data->end_frame)
|
||||
return evaltime;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
snapblock = (int)((evaltime - data->offset) / 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;
|
||||
return ((float)snapblock * data->step_size) + data->offset;
|
||||
}
|
||||
|
||||
static FModifierTypeInfo FMI_STEPPED = {
|
||||
@ -1201,14 +1211,20 @@ short list_has_suitable_fmodifier (ListBase *modifiers, int mtype, short acttype
|
||||
float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime)
|
||||
{
|
||||
FModifier *fcm;
|
||||
float m_evaltime= evaltime;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, modifiers, modifiers->last)
|
||||
return evaltime;
|
||||
|
||||
/* find the first modifier from end of stack that modifies time, and calculate the time the modifier
|
||||
* would calculate time at
|
||||
/* Starting from the end of the stack, calculate the time effects of various stacked modifiers
|
||||
* on the time the F-Curve should be evaluated at.
|
||||
*
|
||||
* This is done in reverse order to standard evaluation, as when this is done in standard
|
||||
* order, each modifier would cause jumps to other points in the curve, forcing all
|
||||
* previous ones to be evaluated again for them to be correct. However, if we did in the
|
||||
* reverse order as we have here, we can consider them a macro to micro type of waterfall
|
||||
* effect, which should get us the desired effects when using layered time manipulations
|
||||
* (such as multiple 'stepped' modifiers in sequence, causing different stepping rates)
|
||||
*/
|
||||
for (fcm= modifiers->last; fcm; fcm= fcm->prev) {
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
@ -1217,13 +1233,12 @@ float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue,
|
||||
// TODO: implement the 'influence' control feature...
|
||||
if (fmi && fmi->evaluate_modifier_time) {
|
||||
if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
|
||||
m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
|
||||
break;
|
||||
evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
|
||||
}
|
||||
}
|
||||
|
||||
/* return the modified evaltime */
|
||||
return m_evaltime;
|
||||
return evaltime;
|
||||
}
|
||||
|
||||
/* Evalautes the given set of F-Curve Modifiers using the given data
|
||||
|
@ -42,6 +42,8 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_fcurve.h"
|
||||
|
||||
@ -252,15 +254,15 @@ static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, shor
|
||||
|
||||
/* before range */
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemL(col, "Before:", 0);
|
||||
uiItemR(col, "", 0, &ptr, "before_mode", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "before_cycles", 0);
|
||||
uiItemL(col, "Before:", 0);
|
||||
uiItemR(col, "", 0, &ptr, "before_mode", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "before_cycles", 0);
|
||||
|
||||
/* after range */
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemL(col, "After:", 0);
|
||||
uiItemR(col, "", 0, &ptr, "after_mode", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "after_cycles", 0);
|
||||
uiItemL(col, "After:", 0);
|
||||
uiItemR(col, "", 0, &ptr, "after_mode", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "after_cycles", 0);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
@ -282,13 +284,13 @@ static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short
|
||||
|
||||
/* col 1 */
|
||||
col= uiLayoutColumn(split, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "size", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "strength", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "size", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "strength", 0);
|
||||
|
||||
/* col 2 */
|
||||
col= uiLayoutColumn(split, 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "phase", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "depth", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "phase", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "depth", 0);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
@ -525,16 +527,16 @@ static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, shor
|
||||
|
||||
/* x-minimum */
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_minimum_x", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "minimum_x", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_minimum_x", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "minimum_x", 0);
|
||||
|
||||
/* y-minimum*/
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_minimum_y", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "minimum_y", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_minimum_y", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "minimum_y", 0);
|
||||
}
|
||||
|
||||
/* row 2: minimum */
|
||||
/* row 2: maximum */
|
||||
{
|
||||
row= uiLayoutRow(layout, 0);
|
||||
|
||||
@ -543,13 +545,13 @@ static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, shor
|
||||
|
||||
/* x-minimum */
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_maximum_x", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "maximum_x", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_maximum_x", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "maximum_x", 0);
|
||||
|
||||
/* y-minimum*/
|
||||
col= uiLayoutColumn(split, 1);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_maximum_y", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "maximum_y", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_maximum_y", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "maximum_y", 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -558,16 +560,32 @@ 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;
|
||||
uiLayout *col, *subcol;
|
||||
PointerRNA ptr;
|
||||
|
||||
/* init the RNA-pointer */
|
||||
RNA_pointer_create(id, &RNA_FModifierStepped, fcm, &ptr);
|
||||
|
||||
/* block 1: "stepping" settings */
|
||||
col= uiLayoutColumn(layout, 0);
|
||||
|
||||
uiItemR(col, NULL, 0, &ptr, "step_size", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "start_offset", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "step_size", 0);
|
||||
uiItemR(col, NULL, 0, &ptr, "offset", 0);
|
||||
|
||||
/* block 2: start range settings */
|
||||
col= uiLayoutColumn(layout, 1);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_start_frame", 0);
|
||||
|
||||
subcol = uiLayoutColumn(col, 1);
|
||||
uiLayoutSetActive(subcol, RNA_boolean_get(&ptr, "use_start_frame"));
|
||||
uiItemR(subcol, NULL, 0, &ptr, "start_frame", 0);
|
||||
|
||||
/* block 3: end range settings */
|
||||
col= uiLayoutColumn(layout, 1);
|
||||
uiItemR(col, NULL, 0, &ptr, "use_end_frame", 0);
|
||||
|
||||
subcol = uiLayoutColumn(col, 1);
|
||||
uiLayoutSetActive(subcol, RNA_boolean_get(&ptr, "use_end_frame"));
|
||||
uiItemR(subcol, NULL, 0, &ptr, "end_frame", 0);
|
||||
}
|
||||
|
||||
/* --------------- */
|
||||
|
@ -236,9 +236,20 @@ typedef enum 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 */
|
||||
float offset; /* Reference frame number that stepping starts from */
|
||||
|
||||
float start_frame; /* start frame of the frame range that modifier works in */
|
||||
float end_frame; /* end frame of the frame range that modifier works in */
|
||||
|
||||
int flag; /* various settings */
|
||||
} FMod_Stepped;
|
||||
|
||||
/* stepped modifier range flags */
|
||||
typedef enum eFMod_Stepped_Flags {
|
||||
FCM_STEPPED_NO_BEFORE = (1<<0), /* don't affect frames before the start frame */
|
||||
FCM_STEPPED_NO_AFTER = (1<<1), /* don't affect frames after the end frame */
|
||||
} eFMod_Stepped_Flags;
|
||||
|
||||
/* Drivers -------------------------------------- */
|
||||
|
||||
/* Driver Target (dtar)
|
||||
|
@ -406,6 +406,61 @@ static void rna_FModifierGenerator_coefficients_set(PointerRNA *ptr, const float
|
||||
memcpy(gen->coefficients, values, gen->arraysize * sizeof(float));
|
||||
}
|
||||
|
||||
static void rna_FModifierLimits_minx_range(PointerRNA *ptr, float *min, float *max)
|
||||
{
|
||||
FModifier *fcm= (FModifier*)ptr->data;
|
||||
FMod_Limits *data= fcm->data;
|
||||
|
||||
*min= MINAFRAMEF;
|
||||
*max= (data->flag & FCM_LIMIT_XMAX)? data->rect.xmax : MAXFRAMEF;
|
||||
}
|
||||
|
||||
static void rna_FModifierLimits_maxx_range(PointerRNA *ptr, float *min, float *max)
|
||||
{
|
||||
FModifier *fcm= (FModifier*)ptr->data;
|
||||
FMod_Limits *data= fcm->data;
|
||||
|
||||
*min= (data->flag & FCM_LIMIT_XMIN)? data->rect.xmin : MINAFRAMEF;
|
||||
*max= MAXFRAMEF;
|
||||
}
|
||||
|
||||
static void rna_FModifierLimits_miny_range(PointerRNA *ptr, float *min, float *max)
|
||||
{
|
||||
FModifier *fcm= (FModifier*)ptr->data;
|
||||
FMod_Limits *data= fcm->data;
|
||||
|
||||
*min= -FLT_MAX;
|
||||
*max= (data->flag & FCM_LIMIT_YMAX)? data->rect.ymax : FLT_MAX;
|
||||
}
|
||||
|
||||
static void rna_FModifierLimits_maxy_range(PointerRNA *ptr, float *min, float *max)
|
||||
{
|
||||
FModifier *fcm= (FModifier*)ptr->data;
|
||||
FMod_Limits *data= fcm->data;
|
||||
|
||||
*min= (data->flag & FCM_LIMIT_YMIN)? data->rect.ymin : -FLT_MAX;
|
||||
*max= FLT_MAX;
|
||||
}
|
||||
|
||||
|
||||
static void rna_FModifierStepped_start_frame_range(PointerRNA *ptr, float *min, float *max)
|
||||
{
|
||||
FModifier *fcm= (FModifier*)ptr->data;
|
||||
FMod_Stepped *data= fcm->data;
|
||||
|
||||
*min= MINAFRAMEF;
|
||||
*max= (data->flag & FCM_STEPPED_NO_AFTER)? data->end_frame : MAXFRAMEF;
|
||||
}
|
||||
|
||||
static void rna_FModifierStepped_end_frame_range(PointerRNA *ptr, float *min, float *max)
|
||||
{
|
||||
FModifier *fcm= (FModifier*)ptr->data;
|
||||
FMod_Stepped *data= fcm->data;
|
||||
|
||||
*min= (data->flag & FCM_STEPPED_NO_BEFORE)? data->start_frame : MINAFRAMEF;
|
||||
*max= MAXFRAMEF;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_fmodifier_generator(BlenderRNA *brna)
|
||||
@ -651,21 +706,25 @@ static void rna_def_fmodifier_limits(BlenderRNA *brna)
|
||||
|
||||
prop= RNA_def_property(srna, "minimum_x", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "rect.xmin");
|
||||
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifierLimits_minx_range");
|
||||
RNA_def_property_ui_text(prop, "Minimum X", "Lowest X value to allow");
|
||||
RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "minimum_y", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "rect.ymin");
|
||||
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifierLimits_miny_range");
|
||||
RNA_def_property_ui_text(prop, "Minimum Y", "Lowest Y value to allow");
|
||||
RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "maximum_x", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "rect.xmax");
|
||||
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifierLimits_maxx_range");
|
||||
RNA_def_property_ui_text(prop, "Maximum X", "Highest X value to allow");
|
||||
RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "maximum_y", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "rect.ymax");
|
||||
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifierLimits_maxy_range");
|
||||
RNA_def_property_ui_text(prop, "Maximum Y", "Highest Y value to allow");
|
||||
RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
}
|
||||
@ -731,9 +790,29 @@ static void rna_def_fmodifier_stepped(BlenderRNA *brna)
|
||||
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");
|
||||
prop= RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "offset");
|
||||
RNA_def_property_ui_text(prop, "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);
|
||||
|
||||
prop= RNA_def_property(srna, "use_start_frame", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_STEPPED_NO_BEFORE);
|
||||
RNA_def_property_ui_text(prop, "Use Start Frame", "Restrict modifier to only act after its 'start' frame");
|
||||
RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "use_end_frame", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", FCM_STEPPED_NO_AFTER);
|
||||
RNA_def_property_ui_text(prop, "Use End Frame", "Restrict modifier to only act before its 'end' frame");
|
||||
RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "start_frame", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifierStepped_start_frame_range");
|
||||
RNA_def_property_ui_text(prop, "Start Frame", "Frame that modifier's influence starts (if applicable)");
|
||||
RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "end_frame", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifierStepped_end_frame_range");
|
||||
RNA_def_property_ui_text(prop, "End Frame", "Frame that modifier's influence ends (if applicable)");
|
||||
RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user