F-Curve Modifiers: Groundwork for getting these working
- Completed cleaning up the drawing code so that F-Curves with modifiers now get drawn to reflect this. - Added a temporary operator to add modifiers (hotkey Ctrl-Shift-M)
This commit is contained in:
@@ -44,6 +44,8 @@ typedef struct FModifierTypeInfo {
|
||||
/* admin/ident */
|
||||
short type; /* FMODIFIER_TYPE_### */
|
||||
short size; /* size in bytes of the struct */
|
||||
short acttype; /* eFMI_Action_Types */
|
||||
short requires; /* eFMI_Requirement_Flags */
|
||||
char name[32]; /* name of modifier in interface */
|
||||
char structName[32]; /* name of struct for SDNA */
|
||||
|
||||
@@ -60,13 +62,37 @@ typedef struct FModifierTypeInfo {
|
||||
void (*evaluate_modifier)(struct FCurve *fcu, struct FModifier *fcm, float *cvalue, float evaltime);
|
||||
} FModifierTypeInfo;
|
||||
|
||||
/* Values which describe the behaviour of a FModifier Type */
|
||||
enum {
|
||||
/* modifier only modifies values outside of data range */
|
||||
FMI_TYPE_EXTRAPOLATION = 0,
|
||||
/* modifier leaves data-points alone, but adjusts the interpolation between and around them */
|
||||
FMI_TYPE_INTERPOLATION,
|
||||
/* modifier only modifies the values of points (but times stay the same) */
|
||||
FMI_TYPE_REPLACE_VALUES,
|
||||
/* modifier generates a curve regardless of what came before */
|
||||
FMI_TYPE_GENERATE_CURVE,
|
||||
} eFMI_Action_Types;
|
||||
|
||||
/* Flags for the requirements of a FModifier Type */
|
||||
enum {
|
||||
/* modifier requires original data-points (kindof beats the purpose of a modifier stack?) */
|
||||
FMI_REQUIRES_ORIGINAL_DATA = (1<<0),
|
||||
/* modifier doesn't require on any preceeding data (i.e. it will generate a curve).
|
||||
* Use in conjunction with FMI_TYPE_GENRATE_CURVE
|
||||
*/
|
||||
FMI_REQUIRES_NOTHING = (1<<1),
|
||||
/* refer to modifier instance */
|
||||
FMI_REQUIRES_RUNTIME_CHECK = (1<<2),
|
||||
} eFMI_Requirement_Flags;
|
||||
|
||||
/* Function Prototypes for FModifierTypeInfo's */
|
||||
FModifierTypeInfo *fmodifier_get_typeinfo(struct FModifier *fcm);
|
||||
FModifierTypeInfo *get_fmodifier_typeinfo(int type);
|
||||
|
||||
/* ---------------------- */
|
||||
|
||||
// TODO... general API here..
|
||||
struct FModifier *fcurve_active_modifier(struct FCurve *fcu);
|
||||
struct FModifier *fcurve_add_modifier(struct FCurve *fcu, int type);
|
||||
void fcurve_copy_modifiers(ListBase *dst, ListBase *src);
|
||||
void fcurve_remove_modifier(struct FCurve *fcu, struct FModifier *fcm);
|
||||
|
||||
@@ -1105,6 +1105,8 @@ static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime)
|
||||
static FModifierTypeInfo FMI_MODNAME = {
|
||||
FMODIFIER_TYPE_MODNAME, /* type */
|
||||
sizeof(FMod_ModName), /* size */
|
||||
FMI_TYPE_SOME_ACTION, /* action type */
|
||||
FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */
|
||||
"Modifier Name", /* name */
|
||||
"FMod_ModName", /* struct name */
|
||||
fcm_modname_free, /* free data */
|
||||
@@ -1155,6 +1157,7 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue,
|
||||
|
||||
/* behaviour depends on mode (NOTE: we don't need to do anything...) */
|
||||
switch (data->mode) {
|
||||
// TODO: implement factorised polynomial too
|
||||
case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
|
||||
{
|
||||
/* we overwrite cvalue with the sum of the polynomial */
|
||||
@@ -1184,6 +1187,8 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue,
|
||||
static FModifierTypeInfo FMI_GENERATOR = {
|
||||
FMODIFIER_TYPE_GENERATOR, /* type */
|
||||
sizeof(FMod_Generator), /* size */
|
||||
FMI_TYPE_GENERATE_CURVE, /* action type */
|
||||
FMI_REQUIRES_NOTHING, /* requirements */
|
||||
"Generator", /* name */
|
||||
"FMod_Generator", /* struct name */
|
||||
fcm_generator_free, /* free data */
|
||||
@@ -1266,6 +1271,8 @@ static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, f
|
||||
static FModifierTypeInfo FMI_ENVELOPE = {
|
||||
FMODIFIER_TYPE_ENVELOPE, /* type */
|
||||
sizeof(FMod_Envelope), /* size */
|
||||
FMI_TYPE_REPLACE_VALUES, /* action type */
|
||||
0, /* requirements */
|
||||
"Envelope", /* name */
|
||||
"FMod_Envelope", /* struct name */
|
||||
fcm_envelope_free, /* free data */
|
||||
@@ -1399,6 +1406,8 @@ static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, flo
|
||||
static FModifierTypeInfo FMI_CYCLES = {
|
||||
FMODIFIER_TYPE_CYCLES, /* type */
|
||||
sizeof(FMod_Cycles), /* size */
|
||||
FMI_TYPE_EXTRAPOLATION, /* action type */
|
||||
FMI_REQUIRES_ORIGINAL_DATA, /* requirements */
|
||||
"Cycles", /* name */
|
||||
"FMod_Cycles", /* struct name */
|
||||
NULL, /* free data */
|
||||
@@ -1413,6 +1422,8 @@ static FModifierTypeInfo FMI_CYCLES = {
|
||||
static FModifierTypeInfo FMI_NOISE = {
|
||||
FMODIFIER_TYPE_NOISE, /* type */
|
||||
sizeof(FMod_Noise), /* size */
|
||||
FMI_TYPE_REPLACE_VALUES, /* action type */
|
||||
0, /* requirements */
|
||||
"Noise", /* name */
|
||||
"FMod_Noise", /* struct name */
|
||||
NULL, /* free data */
|
||||
@@ -1428,6 +1439,8 @@ static FModifierTypeInfo FMI_NOISE = {
|
||||
static FModifierTypeInfo FMI_FILTER = {
|
||||
FMODIFIER_TYPE_FILTER, /* type */
|
||||
sizeof(FMod_Filter), /* size */
|
||||
FMI_TYPE_REPLACE_VALUES, /* action type */
|
||||
0, /* requirements */
|
||||
"Filter", /* name */
|
||||
"FMod_Filter", /* struct name */
|
||||
NULL, /* free data */
|
||||
@@ -1480,6 +1493,8 @@ static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, flo
|
||||
static FModifierTypeInfo FMI_PYTHON = {
|
||||
FMODIFIER_TYPE_PYTHON, /* type */
|
||||
sizeof(FMod_Python), /* size */
|
||||
FMI_TYPE_GENERATE_CURVE, /* action type */
|
||||
FMI_REQUIRES_RUNTIME_CHECK, /* requirements */
|
||||
"Python", /* name */
|
||||
"FMod_Python", /* struct name */
|
||||
fcm_python_free, /* free data */
|
||||
@@ -1499,7 +1514,8 @@ static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES];
|
||||
static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */
|
||||
|
||||
/* This function only gets called when FMI_INIT is non-zero */
|
||||
static void fmods_init_typeinfo () {
|
||||
static void fmods_init_typeinfo ()
|
||||
{
|
||||
fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */
|
||||
fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */
|
||||
fmodifiersTypeInfo[2]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */
|
||||
@@ -1568,6 +1584,8 @@ FModifier *fcurve_add_modifier (FCurve *fcu, int type)
|
||||
|
||||
/* add modifier itself */
|
||||
fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier");
|
||||
fcm->type = type;
|
||||
fcm->flag = FMODIFIER_FLAG_EXPANDED;
|
||||
BLI_addtail(&fcu->modifiers, fcm);
|
||||
|
||||
/* add modifier's data */
|
||||
@@ -1674,12 +1692,30 @@ void fcurve_bake_modifiers (FCurve *fcu, int start, int end)
|
||||
fcu->driver= driver;
|
||||
}
|
||||
|
||||
/* Find the active F-Curve Modifier */
|
||||
FModifier *fcurve_active_modifier (FCurve *fcu)
|
||||
{
|
||||
FModifier *fcm;
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, fcu, fcu->modifiers.first)
|
||||
return NULL;
|
||||
|
||||
/* loop over modifiers until 'active' one is found */
|
||||
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
|
||||
if (fcm->flag & FMODIFIER_FLAG_ACTIVE)
|
||||
return fcm;
|
||||
}
|
||||
|
||||
/* no modifier is active */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ***************************** F-Curve - Evaluation ********************************* */
|
||||
|
||||
/* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime")
|
||||
* Note: this is also used for drivers
|
||||
*/
|
||||
// TODO: set up the modifier system...
|
||||
float evaluate_fcurve (FCurve *fcu, float evaltime)
|
||||
{
|
||||
FModifier *fcm;
|
||||
|
||||
@@ -310,6 +310,12 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
|
||||
/* quick macro to test if AnimData is usable for drivers */
|
||||
#define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first)
|
||||
|
||||
/* quick macro to test if a anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
|
||||
#define ANIMCHANNEL_SELOK(test_func) \
|
||||
( !(filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) || \
|
||||
((filter_mode & ANIMFILTER_SEL) && test_func) || \
|
||||
((filter_mode & ANIMFILTER_UNSEL) && test_func==0) )
|
||||
|
||||
/* ----------- 'Private' Stuff --------------- */
|
||||
|
||||
/* this function allocates memory for a new bAnimListElem struct for the
|
||||
@@ -509,8 +515,8 @@ static int animdata_filter_fcurves (ListBase *anim_data, FCurve *first, bActionG
|
||||
if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
|
||||
/* only work with this channel and its subchannels if it is editable */
|
||||
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
|
||||
/* only include this curve if selected */
|
||||
if (!(filter_mode & ANIMFILTER_SEL) || (SEL_FCU(fcu))) {
|
||||
/* only include this curve if selected in a way consistent with the filtering requirements */
|
||||
if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) ) {
|
||||
/* only include if this curve is active */
|
||||
if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
|
||||
/* owner/ownertype will be either object or action-channel, depending if it was dopesheet or part of an action */
|
||||
@@ -543,7 +549,7 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter
|
||||
/* add this group as a channel first */
|
||||
if ((filter_mode & ANIMFILTER_CHANNELS) || !(filter_mode & ANIMFILTER_CURVESONLY)) {
|
||||
/* check if filtering by selection */
|
||||
if ( !(filter_mode & ANIMFILTER_SEL) || SEL_AGRP(agrp) ) {
|
||||
if ( ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) ) {
|
||||
ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, NULL, ANIMTYPE_NONE, owner_id);
|
||||
if (ale) {
|
||||
BLI_addtail(anim_data, ale);
|
||||
@@ -569,8 +575,7 @@ static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter
|
||||
* - we're interested in keyframes, but not if they appear in selected channels
|
||||
*/
|
||||
if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) ||
|
||||
( (!(filter_mode & ANIMFILTER_SEL) || (SEL_AGRP(agrp))) &&
|
||||
(filter_mode & ANIMFILTER_CURVESONLY) ) )
|
||||
( ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) && (filter_mode & ANIMFILTER_CURVESONLY) ) )
|
||||
{
|
||||
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
|
||||
// XXX the 'owner' info here needs review...
|
||||
@@ -709,7 +714,7 @@ static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter
|
||||
/* loop over layers as the conditions are acceptable */
|
||||
for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
|
||||
/* only if selected */
|
||||
if (!(filter_mode & ANIMFILTER_SEL) || SEL_GPL(gpl)) {
|
||||
if ( ANIMCHANNEL_SELOK(SEL_GPL(gpl)) ) {
|
||||
/* only if editable */
|
||||
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
|
||||
/* add to list */
|
||||
@@ -784,7 +789,6 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
|
||||
|
||||
/* add material's F-Curve channels? */
|
||||
if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
|
||||
//items += animdata_filter_ipocurves(anim_data, ma->ipo, filter_mode, base, ANIMTYPE_OBJECT, (ID *)ma);
|
||||
// XXX the 'owner' info here is still subject to improvement
|
||||
items += animdata_filter_action(anim_data, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);
|
||||
}
|
||||
@@ -873,7 +877,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
|
||||
/* add this object as a channel first */
|
||||
if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
|
||||
/* check if filtering by selection */
|
||||
if ( !(filter_mode & ANIMFILTER_SEL) || ((base->flag & SELECT) || (base == sce->basact)) ) {
|
||||
if (ANIMCHANNEL_SELOK( ((base->flag & SELECT) || (base == sce->basact)) )) {
|
||||
ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, NULL);
|
||||
if (ale) {
|
||||
BLI_addtail(anim_data, ale);
|
||||
@@ -1041,7 +1045,7 @@ static int animdata_filter_dopesheet_scene (ListBase *anim_data, bDopeSheet *ads
|
||||
/* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */
|
||||
if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
|
||||
/* check if filtering by selection */
|
||||
if ( !(filter_mode & ANIMFILTER_SEL) || (sce->flag & SCE_DS_SELECTED) ) {
|
||||
if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) {
|
||||
ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL);
|
||||
if (ale) {
|
||||
BLI_addtail(anim_data, ale);
|
||||
|
||||
@@ -149,12 +149,13 @@ typedef enum eAnim_KeyType {
|
||||
typedef enum eAnimFilter_Flags {
|
||||
ANIMFILTER_VISIBLE = (1<<0), /* should channels be visible (in terms of hierarchy only) */
|
||||
ANIMFILTER_SEL = (1<<1), /* should channels be selected */
|
||||
ANIMFILTER_FOREDIT = (1<<2), /* does editable status matter */
|
||||
ANIMFILTER_CURVESONLY = (1<<3), /* don't include summary-channels, etc. */
|
||||
ANIMFILTER_CHANNELS = (1<<4), /* make list for interface drawing */
|
||||
ANIMFILTER_ACTGROUPED = (1<<5), /* belongs to the active actiongroup */
|
||||
ANIMFILTER_CURVEVISIBLE = (1<<6), /* F-Curve is visible for editing/viewing in Graph Editor */
|
||||
ANIMFILTER_ACTIVE = (1<<7), /* channel should be 'active' */ // FIXME: this is only relevant for F-Curves for now
|
||||
ANIMFILTER_UNSEL = (1<<2), /* should channels be NOT selected */
|
||||
ANIMFILTER_FOREDIT = (1<<3), /* does editable status matter */
|
||||
ANIMFILTER_CURVESONLY = (1<<4), /* don't include summary-channels, etc. */
|
||||
ANIMFILTER_CHANNELS = (1<<5), /* make list for interface drawing */
|
||||
ANIMFILTER_ACTGROUPED = (1<<6), /* belongs to the active actiongroup */
|
||||
ANIMFILTER_CURVEVISIBLE = (1<<7), /* F-Curve is visible for editing/viewing in Graph Editor */
|
||||
ANIMFILTER_ACTIVE = (1<<8), /* channel should be 'active' */ // FIXME: this is only relevant for F-Curves for now
|
||||
} eAnimFilter_Flags;
|
||||
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_scene.h"
|
||||
@@ -218,32 +219,92 @@ static void graph_panel_drivers(const bContext *C, ARegion *ar, short cntrl, bAn
|
||||
|
||||
/* -------------- */
|
||||
|
||||
#define B_FMODIFIER_REDRAW 20
|
||||
|
||||
static void do_graph_region_modifier_buttons(bContext *C, void *arg, int event)
|
||||
{
|
||||
//Scene *scene= CTX_data_scene(C);
|
||||
|
||||
switch(event) {
|
||||
case B_REDR:
|
||||
case B_FMODIFIER_REDRAW:
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
return; /* no notifier! */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* for now, just print name of modifier */
|
||||
static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco)
|
||||
{
|
||||
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
|
||||
uiBut *but;
|
||||
short active= (fcm->flag & FMODIFIER_FLAG_ACTIVE);
|
||||
short width= 314;
|
||||
short height = 0;
|
||||
int rb_col;
|
||||
|
||||
/* draw header */
|
||||
{
|
||||
uiBlockSetEmboss(block, UI_EMBOSSN);
|
||||
|
||||
/* rounded header */
|
||||
if (active) uiBlockSetCol(block, TH_BUT_ACTION);
|
||||
rb_col= (active)?-20:20;
|
||||
uiDefBut(block, ROUNDBOX, B_REDR, "", 10-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15.0, (float)(rb_col-20), "");
|
||||
if (active) uiBlockSetCol(block, TH_AUTO);
|
||||
|
||||
/* expand */
|
||||
uiDefIconButBitS(block, ICONTOG, FMODIFIER_FLAG_EXPANDED, B_REDR, ICON_TRIA_RIGHT, 10-7, *yco-1, 20, 20, &fcm->flag, 0.0, 0.0, 0, 0, "Modifier is expanded");
|
||||
|
||||
/* name */
|
||||
if (fmi)
|
||||
uiDefBut(block, LABEL, 1, fmi->name, 10+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type");
|
||||
else
|
||||
uiDefBut(block, LABEL, 1, "<Unknown Modifier>", 10+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "F-Curve Modifier Type");
|
||||
|
||||
/* delete button */
|
||||
but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 10+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
|
||||
//uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
|
||||
uiBlockSetEmboss(block, UI_EMBOSS);
|
||||
}
|
||||
|
||||
/* default for now */
|
||||
//WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
|
||||
/* when modifier is expanded, draw settings */
|
||||
if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
|
||||
height= 97;
|
||||
|
||||
/* draw backdrop */
|
||||
if (active) uiBlockSetCol(block, TH_BUT_ACTION);
|
||||
uiDefBut(block, ROUNDBOX, B_REDR, "", 10-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, "");
|
||||
if (active) uiBlockSetCol(block, TH_AUTO);
|
||||
}
|
||||
|
||||
/* adjust height for new to start */
|
||||
(*yco) -= (height + 27);
|
||||
}
|
||||
|
||||
static void graph_panel_modifiers(const bContext *C, ARegion *ar, short cntrl, bAnimListElem *ale)
|
||||
{
|
||||
//FCurve *fcu= (FCurve *)ale->data;
|
||||
//FModifier *fcm;
|
||||
FCurve *fcu= (FCurve *)ale->data;
|
||||
FModifier *fcm;
|
||||
uiBlock *block;
|
||||
int yco= 190;
|
||||
|
||||
block= uiBeginBlock(C, ar, "graph_panel_modifiers", UI_EMBOSS, UI_HELV);
|
||||
if (uiNewPanel(C, ar, block, "Modifiers", "Graph", 340, 30, 318, 254)==0) return;
|
||||
uiBlockSetHandleFunc(block, do_graph_region_modifier_buttons, NULL);
|
||||
|
||||
/* to force height */
|
||||
uiNewPanelHeight(block, 204); // XXX variable height!
|
||||
|
||||
/* 'add modifier' button at top of panel */
|
||||
// XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
|
||||
uiDefButO(block, BUT, "GRAPHEDIT_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 225, 150, 20, "Adds a new F-Curve Modifier for the active F-Curve");
|
||||
|
||||
/* draw each modifier */
|
||||
for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next)
|
||||
graph_panel_modifier_draw(block, fcu, fcm, &yco);
|
||||
|
||||
/* since these buttons can have variable height */
|
||||
if (yco < 0)
|
||||
uiNewPanelHeight(block, (204 - yco));
|
||||
else
|
||||
uiNewPanelHeight(block, 204);
|
||||
}
|
||||
|
||||
/* -------------- */
|
||||
@@ -253,7 +314,7 @@ static void graph_panel_modifiers(const bContext *C, ARegion *ar, short cntrl, b
|
||||
* when the caller is done with it.
|
||||
*/
|
||||
// TODO: move this to anim api with another name?
|
||||
static bAnimListElem *get_active_fcurve_channel (bAnimContext *ac)
|
||||
bAnimListElem *get_active_fcurve_channel (bAnimContext *ac)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
int filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ACTIVE | ANIMFILTER_CURVESONLY);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
@@ -401,9 +402,62 @@ static void draw_fcurve_samples (SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
|
||||
|
||||
/* Curve ---------------- */
|
||||
|
||||
/* minimum pixels per gridstep
|
||||
* XXX: defined in view2d.c - must keep these in sync or relocate to View2D header!
|
||||
*/
|
||||
#define MINGRIDSTEP 35
|
||||
|
||||
/* helper func - just draw the F-Curve by sampling the visible region (for drawing curves with modifiers) */
|
||||
static void draw_fcurve_curve (FCurve *fcu, SpaceIpo *sipo, View2D *v2d, View2DGrid *grid)
|
||||
{
|
||||
ChannelDriver *driver;
|
||||
float samplefreq, ctime;
|
||||
float stime, etime;
|
||||
|
||||
/* disable any drivers temporarily */
|
||||
driver= fcu->driver;
|
||||
fcu->driver= NULL;
|
||||
|
||||
|
||||
/* Note about sampling frequency:
|
||||
* Ideally, this is chosen such that we have 1-2 pixels = 1 segment
|
||||
* which means that our curves can be as smooth as possible. However,
|
||||
* this does mean that curves may not be fully accurate (i.e. if they have
|
||||
* sudden spikes which happen at the sampling point, we may have problems).
|
||||
* Also, this may introduce lower performance on less densely detailed curves,'
|
||||
* though it is impossible to predict this from the modifiers!
|
||||
*
|
||||
* If the automatically determined sampling frequency is likely to cause an infinite
|
||||
* loop (i.e. too close to FLT_EPSILON), fall back to default of 0.001
|
||||
*/
|
||||
/* grid->dx is the first float in View2DGrid struct, so just cast to float pointer, and use it
|
||||
* It represents the number of 'frames' between gridlines, but we divide by MINGRIDSTEP to get pixels-steps
|
||||
*/
|
||||
// TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted?
|
||||
samplefreq= *((float *)grid) / MINGRIDSTEP;
|
||||
if (IS_EQ(samplefreq, 0)) samplefreq= 0.001f;
|
||||
|
||||
|
||||
/* the start/end times are simply the horizontal extents of the 'cur' rect */
|
||||
stime= v2d->cur.xmin;
|
||||
etime= v2d->cur.xmax;
|
||||
|
||||
|
||||
/* at each sampling interval, add a new vertex */
|
||||
glBegin(GL_LINE_STRIP);
|
||||
|
||||
for (ctime= stime; ctime <= etime; ctime += samplefreq)
|
||||
glVertex2f( ctime, evaluate_fcurve(fcu, ctime) );
|
||||
|
||||
glEnd();
|
||||
|
||||
/* restore driver */
|
||||
fcu->driver= driver;
|
||||
}
|
||||
|
||||
/* helper func - draw a samples-based F-Curve */
|
||||
// TODO: add offset stuff...
|
||||
static void draw_fcurve_repeat_samples (FCurve *fcu, View2D *v2d)
|
||||
static void draw_fcurve_curve_samples (FCurve *fcu, View2D *v2d)
|
||||
{
|
||||
FPoint *prevfpt= fcu->fpt;
|
||||
FPoint *fpt= prevfpt + 1;
|
||||
@@ -412,26 +466,23 @@ static void draw_fcurve_repeat_samples (FCurve *fcu, View2D *v2d)
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
|
||||
/* extrapolate to left? */
|
||||
if ( (fcu->modifiers.first == NULL)/* || ( ((FModifier *)fcu->modifiers.first)->type != FMODIFIER_TYPE_CYCLES) */) {
|
||||
/* left-side of view comes before first keyframe, so need to extend as not cyclic */
|
||||
if (prevfpt->vec[0] > v2d->cur.xmin) {
|
||||
v[0]= v2d->cur.xmin;
|
||||
|
||||
/* y-value depends on the interpolation */
|
||||
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
|
||||
/* just extend across the first keyframe's value */
|
||||
v[1]= prevfpt->vec[1];
|
||||
}
|
||||
else {
|
||||
/* extrapolate linear dosnt use the handle, use the next points center instead */
|
||||
fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
|
||||
}
|
||||
|
||||
glVertex2fv(v);
|
||||
/* extrapolate to left? - left-side of view comes before first keyframe? */
|
||||
if (prevfpt->vec[0] > v2d->cur.xmin) {
|
||||
v[0]= v2d->cur.xmin;
|
||||
|
||||
/* y-value depends on the interpolation */
|
||||
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
|
||||
/* just extend across the first keyframe's value */
|
||||
v[1]= prevfpt->vec[1];
|
||||
}
|
||||
else {
|
||||
/* extrapolate linear dosnt use the handle, use the next points center instead */
|
||||
fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
|
||||
}
|
||||
|
||||
glVertex2fv(v);
|
||||
}
|
||||
|
||||
/* if only one sample, add it now */
|
||||
@@ -440,7 +491,6 @@ static void draw_fcurve_repeat_samples (FCurve *fcu, View2D *v2d)
|
||||
|
||||
/* loop over samples, drawing segments */
|
||||
/* draw curve between first and last keyframe (if there are enough to do so) */
|
||||
// XXX this doesn't take into account modifiers, or sample data
|
||||
while (b--) {
|
||||
/* Linear interpolation: just add one point (which should add a new line segment) */
|
||||
glVertex2fv(prevfpt->vec);
|
||||
@@ -455,95 +505,90 @@ static void draw_fcurve_repeat_samples (FCurve *fcu, View2D *v2d)
|
||||
}
|
||||
|
||||
/* extrapolate to right? (see code for left-extrapolation above too) */
|
||||
if ( (fcu->modifiers.first == NULL)/* || ( ((FModifier *)fcu->modifiers.first)->type != FMODIFIER_TYPE_CYCLES) */) {
|
||||
if (prevfpt->vec[0] < v2d->cur.xmax) {
|
||||
v[0]= v2d->cur.xmax;
|
||||
|
||||
/* y-value depends on the interpolation */
|
||||
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
|
||||
/* based on last keyframe's value */
|
||||
v[1]= prevfpt->vec[1];
|
||||
}
|
||||
else {
|
||||
/* extrapolate linear dosnt use the handle, use the previous points center instead */
|
||||
fpt = prevfpt-1;
|
||||
fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
|
||||
}
|
||||
|
||||
glVertex2fv(v);
|
||||
if (prevfpt->vec[0] < v2d->cur.xmax) {
|
||||
v[0]= v2d->cur.xmax;
|
||||
|
||||
/* y-value depends on the interpolation */
|
||||
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
|
||||
/* based on last keyframe's value */
|
||||
v[1]= prevfpt->vec[1];
|
||||
}
|
||||
else {
|
||||
/* extrapolate linear dosnt use the handle, use the previous points center instead */
|
||||
fpt = prevfpt-1;
|
||||
fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
|
||||
}
|
||||
|
||||
glVertex2fv(v);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
/* helper func - draw one repeat of an F-Curve */
|
||||
static void draw_fcurve_repeat (FCurve *fcu, View2D *v2d, float cycxofs, float cycyofs, float *facp)
|
||||
static void draw_fcurve_curve_bezts (FCurve *fcu, View2D *v2d, View2DGrid *grid)
|
||||
{
|
||||
BezTriple *prevbezt= fcu->bezt;
|
||||
BezTriple *bezt= prevbezt+1;
|
||||
float v1[2], v2[2], v3[2], v4[2];
|
||||
float *fp, data[120];
|
||||
float fac= *(facp);
|
||||
float fac= 0.0f;
|
||||
int b= fcu->totvert-1;
|
||||
int resol;
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
|
||||
/* extrapolate to left? */
|
||||
if ( (fcu->modifiers.first == NULL)/* || ( ((FModifier *)fcu->modifiers.first)->type != FMODIFIER_TYPE_CYCLES) */) {
|
||||
if (prevbezt->vec[1][0] > v2d->cur.xmin) {
|
||||
/* left-side of view comes before first keyframe, so need to extend as not cyclic */
|
||||
if (prevbezt->vec[1][0] > v2d->cur.xmin) {
|
||||
v1[0]= v2d->cur.xmin;
|
||||
|
||||
/* y-value depends on the interpolation */
|
||||
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
|
||||
/* just extend across the first keyframe's value */
|
||||
v1[1]= prevbezt->vec[1][1];
|
||||
}
|
||||
else if (prevbezt->ipo==BEZT_IPO_LIN) {
|
||||
/* extrapolate linear dosnt use the handle, use the next points center instead */
|
||||
fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
|
||||
}
|
||||
else {
|
||||
/* based on angle of handle 1 (relative to keyframe) */
|
||||
fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
|
||||
}
|
||||
|
||||
glVertex2fv(v1);
|
||||
v1[0]= v2d->cur.xmin;
|
||||
|
||||
/* y-value depends on the interpolation */
|
||||
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
|
||||
/* just extend across the first keyframe's value */
|
||||
v1[1]= prevbezt->vec[1][1];
|
||||
}
|
||||
else if (prevbezt->ipo==BEZT_IPO_LIN) {
|
||||
/* extrapolate linear dosnt use the handle, use the next points center instead */
|
||||
fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
|
||||
}
|
||||
else {
|
||||
/* based on angle of handle 1 (relative to keyframe) */
|
||||
fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
|
||||
}
|
||||
|
||||
glVertex2fv(v1);
|
||||
}
|
||||
|
||||
/* if only one keyframe, add it now */
|
||||
if (fcu->totvert == 1) {
|
||||
v1[0]= prevbezt->vec[1][0] + cycxofs;
|
||||
v1[1]= prevbezt->vec[1][1] + cycyofs;
|
||||
v1[0]= prevbezt->vec[1][0];
|
||||
v1[1]= prevbezt->vec[1][1];
|
||||
glVertex2fv(v1);
|
||||
}
|
||||
|
||||
/* draw curve between first and last keyframe (if there are enough to do so) */
|
||||
// XXX this doesn't take into account modifiers, or sample data
|
||||
while (b--) {
|
||||
if ((fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST)) {
|
||||
/* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */
|
||||
v1[0]= prevbezt->vec[1][0]+cycxofs;
|
||||
v1[1]= prevbezt->vec[1][1]+cycyofs;
|
||||
v1[0]= prevbezt->vec[1][0];
|
||||
v1[1]= prevbezt->vec[1][1];
|
||||
glVertex2fv(v1);
|
||||
|
||||
v1[0]= bezt->vec[1][0]+cycxofs;
|
||||
v1[1]= prevbezt->vec[1][1]+cycyofs;
|
||||
v1[0]= bezt->vec[1][0];
|
||||
v1[1]= prevbezt->vec[1][1];
|
||||
glVertex2fv(v1);
|
||||
}
|
||||
else if (prevbezt->ipo==BEZT_IPO_LIN) {
|
||||
/* Linear interpolation: just add one point (which should add a new line segment) */
|
||||
v1[0]= prevbezt->vec[1][0]+cycxofs;
|
||||
v1[1]= prevbezt->vec[1][1]+cycyofs;
|
||||
v1[0]= prevbezt->vec[1][0];
|
||||
v1[1]= prevbezt->vec[1][1];
|
||||
glVertex2fv(v1);
|
||||
}
|
||||
else {
|
||||
@@ -560,23 +605,23 @@ static void draw_fcurve_repeat (FCurve *fcu, View2D *v2d, float cycxofs, float c
|
||||
|
||||
if (resol < 2) {
|
||||
/* only draw one */
|
||||
v1[0]= prevbezt->vec[1][0]+cycxofs;
|
||||
v1[1]= prevbezt->vec[1][1]+cycyofs;
|
||||
v1[0]= prevbezt->vec[1][0];
|
||||
v1[1]= prevbezt->vec[1][1];
|
||||
glVertex2fv(v1);
|
||||
}
|
||||
else {
|
||||
/* clamp resolution to max of 32 */
|
||||
if (resol > 32) resol= 32;
|
||||
|
||||
v1[0]= prevbezt->vec[1][0]+cycxofs;
|
||||
v1[1]= prevbezt->vec[1][1]+cycyofs;
|
||||
v2[0]= prevbezt->vec[2][0]+cycxofs;
|
||||
v2[1]= prevbezt->vec[2][1]+cycyofs;
|
||||
v1[0]= prevbezt->vec[1][0];
|
||||
v1[1]= prevbezt->vec[1][1];
|
||||
v2[0]= prevbezt->vec[2][0];
|
||||
v2[1]= prevbezt->vec[2][1];
|
||||
|
||||
v3[0]= bezt->vec[0][0]+cycxofs;
|
||||
v3[1]= bezt->vec[0][1]+cycyofs;
|
||||
v4[0]= bezt->vec[1][0]+cycxofs;
|
||||
v4[1]= bezt->vec[1][1]+cycyofs;
|
||||
v3[0]= bezt->vec[0][0];
|
||||
v3[1]= bezt->vec[0][1];
|
||||
v4[0]= bezt->vec[1][0];
|
||||
v4[1]= bezt->vec[1][1];
|
||||
|
||||
correct_bezpart(v1, v2, v3, v4);
|
||||
|
||||
@@ -594,152 +639,41 @@ static void draw_fcurve_repeat (FCurve *fcu, View2D *v2d, float cycxofs, float c
|
||||
|
||||
/* last point? */
|
||||
if (b == 0) {
|
||||
v1[0]= prevbezt->vec[1][0]+cycxofs;
|
||||
v1[1]= prevbezt->vec[1][1]+cycyofs;
|
||||
v1[0]= prevbezt->vec[1][0];
|
||||
v1[1]= prevbezt->vec[1][1];
|
||||
glVertex2fv(v1);
|
||||
}
|
||||
}
|
||||
|
||||
/* extrapolate to right? (see code for left-extrapolation above too) */
|
||||
if ( (fcu->modifiers.first == NULL)/* || ( ((FModifier *)fcu->modifiers.first)->type != FMODIFIER_TYPE_CYCLES) */) {
|
||||
if (prevbezt->vec[1][0] < v2d->cur.xmax) {
|
||||
v1[0]= v2d->cur.xmax;
|
||||
|
||||
/* y-value depends on the interpolation */
|
||||
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
|
||||
/* based on last keyframe's value */
|
||||
v1[1]= prevbezt->vec[1][1];
|
||||
}
|
||||
else if (prevbezt->ipo==BEZT_IPO_LIN) {
|
||||
/* extrapolate linear dosnt use the handle, use the previous points center instead */
|
||||
bezt = prevbezt-1;
|
||||
fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
|
||||
}
|
||||
else {
|
||||
/* based on angle of handle 1 (relative to keyframe) */
|
||||
fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
|
||||
}
|
||||
|
||||
glVertex2fv(v1);
|
||||
if (prevbezt->vec[1][0] < v2d->cur.xmax) {
|
||||
v1[0]= v2d->cur.xmax;
|
||||
|
||||
/* y-value depends on the interpolation */
|
||||
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
|
||||
/* based on last keyframe's value */
|
||||
v1[1]= prevbezt->vec[1][1];
|
||||
}
|
||||
else if (prevbezt->ipo==BEZT_IPO_LIN) {
|
||||
/* extrapolate linear dosnt use the handle, use the previous points center instead */
|
||||
bezt = prevbezt-1;
|
||||
fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
|
||||
}
|
||||
else {
|
||||
/* based on angle of handle 1 (relative to keyframe) */
|
||||
fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
|
||||
if (fac) fac= 1.0f/fac;
|
||||
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
|
||||
}
|
||||
|
||||
glVertex2fv(v1);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
/* return fac, as we alter it */
|
||||
*(facp) = fac;
|
||||
}
|
||||
|
||||
#if 0 // XXX old animation system unconverted code!
|
||||
|
||||
/* draw all ipo-curves */
|
||||
static void draw_ipocurves(SpaceIpo *sipo, ARegion *ar, int sel)
|
||||
{
|
||||
View2D *v2d= &ar->v2d;
|
||||
EditIpo *ei;
|
||||
int nr, val/*, pickselcode=0*/;
|
||||
|
||||
/* if we're drawing for GL_SELECT, reset pickselcode first
|
||||
* - there's only one place that will do this, so it should be fine
|
||||
*/
|
||||
//if (G.f & G_PICKSEL)
|
||||
// pickselcode= 1;
|
||||
|
||||
ei= sipo->editipo;
|
||||
for (nr=0; nr<sipo->totipo; nr++, ei++) {
|
||||
if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
|
||||
/* val is used to indicate if curve can be edited */
|
||||
//if (G.f & G_PICKSEL) {
|
||||
// /* when using OpenGL to select stuff (on mouseclick) */
|
||||
// glLoadName(pickselcode++);
|
||||
// val= 1;
|
||||
//}
|
||||
//else {
|
||||
/* filter to only draw those that are selected or unselected (based on drawing mode */
|
||||
val= (ei->flag & (IPO_SELECT+IPO_EDIT)) != 0;
|
||||
val= (val==sel);
|
||||
//}
|
||||
|
||||
/* only draw those curves that we can draw */
|
||||
if (val) {
|
||||
IpoCurve *icu= ei->icu;
|
||||
float cycdx=0.0f, cycdy=0.0f, cycxofs=0.0f, cycyofs=0.0f;
|
||||
const int lastindex= (icu->totvert-1);
|
||||
float fac= 0.0f;
|
||||
int cycount=1;
|
||||
|
||||
/* set color for curve curve:
|
||||
* - bitflag curves (evil) must always be drawn coloured as they cannot work with IPO-Keys
|
||||
* - when IPO-Keys are shown, individual curves are not editable, so we show by drawing them all black
|
||||
*/
|
||||
if ((sipo->showkey) && (ei->disptype!=IPO_DISPBITS)) UI_ThemeColor(TH_TEXT);
|
||||
else cpack(ei->col);
|
||||
|
||||
/* cyclic curves - get offset and number of repeats to display */
|
||||
if (icu->extrap & IPO_CYCL) {
|
||||
BezTriple *bezt= icu->bezt;
|
||||
BezTriple *lastbezt= bezt + lastindex;
|
||||
|
||||
/* calculate cycle length and amplitude */
|
||||
cycdx= lastbezt->vec[1][0] - bezt->vec[1][0];
|
||||
cycdy= lastbezt->vec[1][1] - bezt->vec[1][1];
|
||||
|
||||
/* check that the cycle does have some length */
|
||||
if (cycdx > 0.01f) {
|
||||
/* count cycles before first frame */
|
||||
while (icu->bezt->vec[1][0]+cycxofs > v2d->cur.xmin) {
|
||||
cycxofs -= cycdx;
|
||||
if (icu->extrap & IPO_DIR) cycyofs-= cycdy;
|
||||
cycount++;
|
||||
}
|
||||
|
||||
/* count cycles after last frame (and adjust offset) */
|
||||
fac= 0.0f;
|
||||
while (lastbezt->vec[1][0]+fac < v2d->cur.xmax) {
|
||||
cycount++;
|
||||
fac += cycdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* repeat process for each repeat */
|
||||
while (cycount--) {
|
||||
/* bitflag curves are drawn differently to normal curves */
|
||||
if (ei->disptype==IPO_DISPBITS)
|
||||
draw_ipocurve_repeat_bits(icu, v2d, cycxofs);
|
||||
else
|
||||
draw_ipocurve_repeat_normal(icu, v2d, cycxofs, cycyofs, &fac);
|
||||
|
||||
/* prepare for next cycle by adjusing offsets */
|
||||
cycxofs += cycdx;
|
||||
if (icu->extrap & IPO_DIR) cycyofs += cycdy;
|
||||
}
|
||||
|
||||
/* vertical line that indicates the end of a speed curve */
|
||||
if ((sipo->blocktype==ID_CU) && (icu->adrcode==CU_SPEED)) {
|
||||
int b= icu->totvert-1;
|
||||
|
||||
if (b) {
|
||||
BezTriple *bezt= icu->bezt+b;
|
||||
|
||||
glColor3ub(0, 0, 0);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(bezt->vec[1][0], 0.0f);
|
||||
glVertex2f(bezt->vec[1][0], bezt->vec[1][1]);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // XXX old animation system unconverted code
|
||||
|
||||
#if 0
|
||||
static void draw_ipokey(SpaceIpo *sipo, ARegion *ar)
|
||||
{
|
||||
@@ -758,7 +692,9 @@ static void draw_ipokey(SpaceIpo *sipo, ARegion *ar)
|
||||
}
|
||||
#endif
|
||||
|
||||
void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
|
||||
/* Public Curve-Drawing API ---------------- */
|
||||
|
||||
void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid *grid)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
@@ -774,20 +710,22 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
|
||||
*/
|
||||
for (ale=anim_data.first; ale; ale=ale->next) {
|
||||
FCurve *fcu= (FCurve *)ale->key_data;
|
||||
Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
float fac=0.0f; // dummy var
|
||||
//FModifier *fcm= fcurve_active_modifier(fcu);
|
||||
//Object *nob= ANIM_nla_mapping_get(ac, ale);
|
||||
|
||||
/* map keyframes for drawing if scaled F-Curve */
|
||||
if (nob)
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 0);
|
||||
//if (nob)
|
||||
// ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 0, 0);
|
||||
|
||||
/* draw curve - if there's an active modifier (or a stack of modifiers) drawing these takes presidence,
|
||||
* unless modifiers in use will not alter any of the values within the keyframed area...
|
||||
/* draw curve:
|
||||
* - curve line may be result of one or more destructive modifiers or just the raw data,
|
||||
* so we need to check which method should be used
|
||||
* - controls from active modifier take precidence over keyframes
|
||||
* (XXX! editing tools need to take this into account!)
|
||||
*/
|
||||
|
||||
|
||||
/* draw curve - as defined by keyframes */
|
||||
if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) {
|
||||
|
||||
/* 1) draw curve line */
|
||||
{
|
||||
/* set color/drawing style for curve itself */
|
||||
if ( ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || (fcu->flag & FCURVE_PROTECTED) ) {
|
||||
/* protected curves (non editable) are drawn with dotted lines */
|
||||
@@ -803,18 +741,35 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
|
||||
glColor3fv(fcu->color);
|
||||
}
|
||||
|
||||
/* anti-aliased lines for less jagged appearance */
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
/* draw F-Curve */
|
||||
if (fcu->bezt)
|
||||
draw_fcurve_repeat(fcu, &ar->v2d, 0, 0, &fac); // XXX this call still needs a lot more work
|
||||
else if (fcu->fpt)
|
||||
draw_fcurve_repeat_samples(fcu, &ar->v2d);
|
||||
/*else modifiers? */
|
||||
if (fcu->modifiers.first) {
|
||||
/* draw a curve affected by modifiers by sampling its points */
|
||||
draw_fcurve_curve(fcu, sipo, &ar->v2d, grid);
|
||||
}
|
||||
else if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) {
|
||||
/* just draw curve based on defined data (i.e. no modifiers) */
|
||||
if (fcu->bezt)
|
||||
draw_fcurve_curve_bezts(fcu, &ar->v2d, grid);
|
||||
else if (fcu->fpt)
|
||||
draw_fcurve_curve_samples(fcu, &ar->v2d);
|
||||
}
|
||||
|
||||
/* restore settings */
|
||||
setlinestyle(0);
|
||||
|
||||
|
||||
/* draw handles and vertices as appropriate */
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
/* 2) draw handles and vertices as appropriate based on active */
|
||||
if ((fcu->modifiers.first) && (fcm) && (fcm->type != FMODIFIER_TYPE_CYCLES)) {
|
||||
// TODO: need to add code to show these... for cycles modifier, should fall through though...
|
||||
}
|
||||
else if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) {
|
||||
if (fcu->bezt) {
|
||||
/* only draw handles/vertices on keyframes */
|
||||
draw_fcurve_handles(sipo, ar, fcu);
|
||||
@@ -827,8 +782,8 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
|
||||
}
|
||||
|
||||
/* undo mapping of keyframes for drawing if scaled F-Curve */
|
||||
if (nob)
|
||||
ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 0);
|
||||
//if (nob)
|
||||
// ANIM_nla_mapping_apply_fcurve(nob, ale->key_data, 1, 0);
|
||||
}
|
||||
|
||||
/* free list of curves */
|
||||
|
||||
@@ -1018,12 +1018,25 @@ void GRAPHEDIT_OT_keyframes_handletype (wmOperatorType *ot)
|
||||
* of values to -180 degrees to 180 degrees.
|
||||
*/
|
||||
|
||||
#if 0 // XXX this is not ready for the primetime yet
|
||||
|
||||
/* set of three euler-rotation F-Curves */
|
||||
typedef struct tEulerFilter {
|
||||
ID *id; /* ID-block which owns the channels */
|
||||
FCurve *fcu1, *fcu2, *fcu3; /* x,y,z rotation curves */
|
||||
int i1, i2, i3; /* current index for each curve */
|
||||
} tEulerFilter;
|
||||
|
||||
static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
//ListBase anim_data= {NULL, NULL};
|
||||
//bAnimListElem *ale;
|
||||
//int filter;
|
||||
|
||||
ListBase anim_data= {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
ListBase eulers = {NULL, NULL};
|
||||
tEulerFilter *euf= NULL;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
@@ -1035,7 +1048,33 @@ static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op)
|
||||
* 2) Each set of three F-Curves is processed for each keyframe, with the values being
|
||||
* processed according to one of several ways.
|
||||
*/
|
||||
|
||||
/* step 1: extract only the rotation f-curves */
|
||||
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_CURVESONLY);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
for (ale= anim_data.first; ale; ale= ale->next) {
|
||||
FCurve *fcu = (FCurve *)ale->data;
|
||||
|
||||
/* check if this is an appropriate F-Curve
|
||||
* - only rotation curves
|
||||
* - for pchan curves, make sure we're only using the euler curves
|
||||
*/
|
||||
if (ELEM(0, fcu->rna_path, strstr(fcu->rna_path, "rotation")))
|
||||
continue;
|
||||
if (strstr(fcu->rna_path, "pose.pose_channels")) {
|
||||
if (strstr(fcu->rna_path, "euler_rotation") == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check if current set of 3-curves is suitable to add this curve to
|
||||
* - things like whether the current set of curves is 'full' should be checked later only
|
||||
* - first check if id-blocks are compatible
|
||||
*/
|
||||
if ((euf) && (ale->id != euf->id)) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// XXX for now
|
||||
return OPERATOR_CANCELLED;
|
||||
@@ -1055,6 +1094,8 @@ void GRAPHEDIT_OT_keyframes_euler_filter (wmOperatorType *ot)
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
#endif // XXX this is not ready for the primetime yet
|
||||
|
||||
/* ***************** Snap Current Frame Operator *********************** */
|
||||
|
||||
/* helper callback for graphkeys_cfrasnap_exec() -> used to help get the average time of all selected beztriples */
|
||||
@@ -1376,3 +1417,76 @@ void GRAPHEDIT_OT_keyframes_smooth (wmOperatorType *ot)
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* F-CURVE MODIFIERS */
|
||||
|
||||
/* ******************** Add F-Curve Modifier Operator *********************** */
|
||||
|
||||
/* F-Modifier types - duplicate of existing codes... */
|
||||
// XXX how can we have this list from the RNA definitions instead?
|
||||
EnumPropertyItem prop_fmodifier_types[] = {
|
||||
{FMODIFIER_TYPE_GENERATOR, "GENERATOR", "Generator", ""},
|
||||
{FMODIFIER_TYPE_ENVELOPE, "ENVELOPE", "Envelope", ""},
|
||||
{FMODIFIER_TYPE_CYCLES, "CYCLES", "Cycles", ""},
|
||||
{FMODIFIER_TYPE_NOISE, "NOISE", "Noise", ""},
|
||||
{FMODIFIER_TYPE_FILTER, "FILTER", "Filter", ""},
|
||||
{FMODIFIER_TYPE_PYTHON, "PYTHON", "Python", ""},
|
||||
{0, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
bAnimListElem *ale;
|
||||
FCurve *fcu;
|
||||
short type;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
// xxx call the raw methods here instead?
|
||||
ale= get_active_fcurve_channel(&ac);
|
||||
if (ale == NULL)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
fcu= (FCurve *)ale->data;
|
||||
MEM_freeN(ale);
|
||||
if (fcu == NULL)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
|
||||
/* get type of modifier to add */
|
||||
type= RNA_enum_get(op->ptr, "type");
|
||||
|
||||
/* add F-Modifier of specified type to active F-Curve */
|
||||
fcurve_add_modifier(fcu, type);
|
||||
|
||||
|
||||
/* validate keyframes after editing */
|
||||
ANIM_editkeyframes_refresh(&ac);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_BOTH);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void GRAPHEDIT_OT_fmodifier_add (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Add F-Curve Modifier";
|
||||
ot->idname= "GRAPHEDIT_OT_fmodifier_add";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= graph_fmodifier_add_exec;
|
||||
ot->poll= ED_operator_areaactive; // XXX need active F-Curve
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
/* id-props */
|
||||
RNA_def_enum(ot->srna, "type", prop_fmodifier_types, 0, "Type", "");
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
|
||||
@@ -31,9 +31,11 @@
|
||||
struct bContext;
|
||||
struct wmWindowManager;
|
||||
struct bAnimContext;
|
||||
struct bAnimListElem;
|
||||
struct SpaceIpo;
|
||||
struct ScrArea;
|
||||
struct ARegion;
|
||||
struct View2DGrid;
|
||||
|
||||
/* internal exports only */
|
||||
|
||||
@@ -44,7 +46,7 @@ struct ARegion *graph_has_buttons_region(struct ScrArea *sa);
|
||||
/* ***************************************** */
|
||||
/* graph_draw.c */
|
||||
void graph_draw_channel_names(struct bAnimContext *ac, struct SpaceIpo *sipo, struct ARegion *ar);
|
||||
void graph_draw_curves(struct bAnimContext *ac, struct SpaceIpo *sipo, struct ARegion *ar);
|
||||
void graph_draw_curves(struct bAnimContext *ac, struct SpaceIpo *sipo, struct ARegion *ar, struct View2DGrid *grid);
|
||||
|
||||
/* ***************************************** */
|
||||
/* graph_header.c */
|
||||
@@ -119,11 +121,17 @@ enum {
|
||||
GRAPHKEYS_MIRROR_MARKER,
|
||||
} eGraphKeys_Mirror_Mode;
|
||||
|
||||
/* ----------- */
|
||||
|
||||
void GRAPHEDIT_OT_fmodifier_add(struct wmOperatorType *ot);
|
||||
|
||||
/* ***************************************** */
|
||||
/* graph_buttons.c */
|
||||
void GRAPHEDIT_OT_properties(struct wmOperatorType *ot);
|
||||
void graph_region_buttons(const struct bContext *C, struct ARegion *ar);
|
||||
|
||||
struct bAnimListElem *get_active_fcurve_channel(struct bAnimContext *ac);
|
||||
|
||||
/* ***************************************** */
|
||||
/* graph_ops.c */
|
||||
void graphedit_keymap(struct wmWindowManager *wm);
|
||||
|
||||
@@ -126,6 +126,10 @@ void graphedit_operatortypes(void)
|
||||
WM_operatortype_append(GRAPHEDIT_OT_keyframes_paste);
|
||||
|
||||
//TODO: insertkey...
|
||||
|
||||
/* F-Curve Modifiers */
|
||||
// XXX temporary?
|
||||
WM_operatortype_append(GRAPHEDIT_OT_fmodifier_add);
|
||||
}
|
||||
|
||||
/* ************************** registration - keymaps **********************************/
|
||||
@@ -195,6 +199,11 @@ static void graphedit_keymap_keyframes (wmWindowManager *wm, ListBase *keymap)
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_set_previewrange", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
|
||||
|
||||
/* F-Curve Modifiers */
|
||||
// XXX these are temporary? operators...
|
||||
WM_keymap_add_item(keymap, "GRAPHEDIT_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
|
||||
|
||||
|
||||
/* transform system */
|
||||
transform_keymap_for_space(wm, keymap, SPACE_IPO);
|
||||
}
|
||||
|
||||
@@ -230,12 +230,13 @@ static void graph_main_area_draw(const bContext *C, ARegion *ar)
|
||||
unitx= (sipo->flag & SIPO_DRAWTIME)? V2D_UNIT_SECONDS : V2D_UNIT_FRAMESCALE;
|
||||
grid= UI_view2d_grid_calc(C, v2d, unitx, V2D_GRID_NOCLAMP, unity, V2D_GRID_NOCLAMP, ar->winx, ar->winy);
|
||||
UI_view2d_grid_draw(C, v2d, grid, V2D_GRIDLINES_ALL);
|
||||
UI_view2d_grid_free(grid);
|
||||
|
||||
/* draw data */
|
||||
if (ANIM_animdata_get_context(C, &ac)) {
|
||||
graph_draw_curves(&ac, sipo, ar);
|
||||
}
|
||||
if (ANIM_animdata_get_context(C, &ac))
|
||||
graph_draw_curves(&ac, sipo, ar, grid);
|
||||
|
||||
/* only free grid after drawing data, as we need to use it to determine sampling rate */
|
||||
UI_view2d_grid_free(grid);
|
||||
|
||||
/* current frame */
|
||||
if (sipo->flag & SIPO_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS;
|
||||
|
||||
Reference in New Issue
Block a user