F-Curve Modifiers: Basic GUI for Generator Modifier working
authorJoshua Leung <aligorith@gmail.com>
Mon, 16 Mar 2009 11:11:44 +0000 (11:11 +0000)
committerJoshua Leung <aligorith@gmail.com>
Mon, 16 Mar 2009 11:11:44 +0000 (11:11 +0000)
* Currently, this only works for the 'Expanded polynomial' mode, but this will be expanded to include the other modes too. Now you can modify the values and interactively see the graph in the view change.

* Disabled the backdrops (modifier 'panels') temporarily, as ROUNDBOX UI elements currently swallow all events, which is not good.

Note: the code here still uses the old-style UI definition code since the new stuff is still under heavy construction.

source/blender/blenkernel/BKE_fcurve.h
source/blender/blenkernel/intern/fcurve.c
source/blender/editors/space_graph/graph_buttons.c
source/blender/editors/space_graph/graph_draw.c
source/blender/editors/space_graph/space_graph.c

index 23c4579de14b6d603dcd1fc33ef9d8fca6c02959..a53785adf172aadaa04b80d973ee73fc951997bf 100644 (file)
@@ -56,6 +56,8 @@ typedef struct FModifierTypeInfo {
        void (*copy_data)(struct FModifier *fcm, struct FModifier *src);
                /* set settings for data that will be used for FCuModifier.data (memory already allocated using MEM_callocN) */
        void (*new_data)(void *mdata);
+               /* verifies that the modifier settings are valid */
+       void (*verify_data)(struct FModifier *fcm);
        
        /* evaluation */
                /* evaluate the modifier for the given time and 'accumulated' value */
index 3b60be396e7bd18ec9c0187f672f6e6b276abdac..e977310ecc836e840b41e95f77c4f11105c8d383 100644 (file)
@@ -1114,6 +1114,7 @@ static FModifierTypeInfo FMI_MODNAME = {
        fcm_modname_relink, /* relink data */
        fcm_modname_copy, /* copy data */
        fcm_modname_new_data, /* new data */
+       fcm_modname_verify, /* verify */
        fcm_modname_evaluate /* evaluate */
 };
 #endif
@@ -1163,6 +1164,45 @@ static void fcm_generator_new_data (void *mdata)
        cp[1] = 1; // gradient
 }
 
+static void fcm_generator_verify (FModifier *fcm)
+{
+       FMod_Generator *data= (FMod_Generator *)fcm->data;
+       
+       /* requirements depend on mode */
+       switch (data->mode) {
+               case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
+               {
+                       /* arraysize needs to be order+1, so resize if not */
+                       if (data->arraysize != (data->poly_order+1)) {
+                               float *nc;
+                               
+                               /* make new coefficients array, and copy over as much data as can fit */
+                               nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs");
+                               
+                               if (data->coefficients) {
+                                       if (data->arraysize > (data->poly_order+1))
+                                               memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1));
+                                       else
+                                               memcpy(nc, data->coefficients, sizeof(float)*data->arraysize);
+                               }       
+                               
+                               /* free the old data, and set the new */
+                               if (data->coefficients) MEM_freeN(data->coefficients);
+                               
+                               data->coefficients= nc;
+                               data->arraysize= data->poly_order+1;
+                       }
+               }
+                       break;
+               
+               // FIXME: add checks for all others             
+               case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */
+               {
+                       
+               }
+                       break;
+       }
+}
 
 static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
 {
@@ -1294,6 +1334,7 @@ static FModifierTypeInfo FMI_GENERATOR = {
        fcm_generator_free, /* free data */
        fcm_generator_copy, /* copy data */
        fcm_generator_new_data, /* new data */
+       fcm_generator_verify, /* verify */
        fcm_generator_evaluate /* evaluate */
 };
 
@@ -1378,6 +1419,7 @@ static FModifierTypeInfo FMI_ENVELOPE = {
        fcm_envelope_free, /* free data */
        fcm_envelope_copy, /* copy data */
        NULL, /* new data */
+       NULL /*fcm_envelope_verify*/, /* verify */
        fcm_envelope_evaluate /* evaluate */
 };
 
@@ -1513,6 +1555,7 @@ static FModifierTypeInfo FMI_CYCLES = {
        NULL, /* free data */
        NULL, /* copy data */
        NULL, /* new data */
+       NULL /*fcm_cycles_verify*/, /* verify */
        fcm_cycles_evaluate /* evaluate */
 };
 
@@ -1529,6 +1572,7 @@ static FModifierTypeInfo FMI_NOISE = {
        NULL, /* free data */
        NULL, /* copy data */
        fcm_noise_new_data, /* new data */
+       NULL /*fcm_noise_verify*/, /* verify */
        fcm_noise_evaluate /* evaluate */
 };
 #endif // XXX not yet implemented
@@ -1546,6 +1590,7 @@ static FModifierTypeInfo FMI_FILTER = {
        NULL, /* free data */
        NULL, /* copy data */
        NULL, /* new data */
+       NULL /*fcm_filter_verify*/, /* verify */
        fcm_filter_evaluate /* evaluate */
 };
 #endif // XXX not yet implemented
@@ -1600,6 +1645,7 @@ static FModifierTypeInfo FMI_PYTHON = {
        fcm_python_free, /* free data */
        fcm_python_copy, /* copy data */
        fcm_python_new_data, /* new data */
+       NULL /*fcm_python_verify*/, /* verify */
        fcm_python_evaluate /* evaluate */
 };
 
@@ -1689,7 +1735,7 @@ FModifier *fcurve_add_modifier (FCurve *fcu, int type)
        BLI_addtail(&fcu->modifiers, fcm);
        
        /* add modifier's data */
-       fcm->data= MEM_callocN(fmi->size, "F-Curve Modifier Data");
+       fcm->data= MEM_callocN(fmi->size, fmi->structName);
                
        /* init custom settings if necessary */
        if (fmi->new_data)      
index c53b6a720de1390f5780c78c06c44a7f15361fc2..a860c25a5633deb85a41cd976f1a9918fd062b22 100644 (file)
@@ -223,51 +223,107 @@ static void graph_panel_drivers(const bContext *C, ARegion *ar, short cntrl, bAn
 
 static void do_graph_region_modifier_buttons(bContext *C, void *arg, int event)
 {
-       switch(event) {
+       switch (event) {
                case B_REDR:
-               case B_FMODIFIER_REDRAW:
+               case B_FMODIFIER_REDRAW: // XXX this should send depsgraph updates too
                        ED_area_tag_redraw(CTX_wm_area(C));
                        return; /* no notifier! */
        }
 }
 
 /* macro for use here to draw background box and set height */
-#define DRAW_BACKDROP(height, h) \
+// XXX for now, roundbox has it's callback func set to NULL to not intercept events
+#define DRAW_BACKDROP(height) \
        { \
-               height= h; \
                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, ""); \
+                       but= uiDefBut(block, ROUNDBOX, B_REDR, "", 10-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \
+                       uiButSetFunc(but, NULL, NULL, NULL); \
                if (active) uiBlockSetCol(block, TH_AUTO); \
        }
 
+/* callback to verify modifier data */
+static void validate_fmodifier_cb (bContext *C, void *fcu_v, void *fcm_v)
+{
+       FModifier *fcm= (FModifier *)fcm_v;
+       FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+       
+       /* call the verify callback on the modifier if applicable */
+       if (fmi && fmi->verify_data)
+               fmi->verify_data(fcm);
+}
+       
 /* draw settings for generator modifier */
 static void _draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col)
 {
        FMod_Generator *data= (FMod_Generator *)fcm->data;
+       char gen_mode[]="Generator Type%t|Expanded Polynomial%x0|Factorised Polynomial%x1|Built-In Function%x2|Expression%x3";
+       //char fn_type[]="Built-In Function%t|Sin%x0|Cos%x1|Tan%x2|Square Root%x3|Natural Log%x4";
+       int cy= *yco - 30;
+       uiBut *but;
        
+       /* set the height */
+       (*height) = 70;
+       switch (data->mode) {
+               case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
+                       (*height) += 20*(data->poly_order+1) + 35;
+                       break;
+               case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */
+                       (*height) += 25 * data->poly_order;
+                       break;
+               case FCM_GENERATOR_FUNCTION: /* builtin function */
+                       (*height) += 50; // xxx
+                       break;
+               case FCM_GENERATOR_EXPRESSION: /* py-expression */
+                       // xxx nothing to draw 
+                       break;
+       }
+       
+       /* basic settings (backdrop + mode selector + some padding) */
+       //DRAW_BACKDROP((*height)); // XXX buggy...
+       but= uiDefButS(block, MENU, /*B_FMODIFIER_REDRAW*/B_REDR, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm.");
+       uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
+       cy -= 35;
+       
+       /* now add settings for individual modifiers */
        switch (data->mode) {
                case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
                {
-                       /* we overwrite cvalue with the sum of the polynomial */
-                       float value= 0.0f, *cp = NULL;
+                       float *cp = NULL;
+                       char xval[32];
                        unsigned int i;
                        
-                       /* draw backdrop */
-                       DRAW_BACKDROP((*height), 96);
+                       /* draw polynomial order selector */
+                               // XXX this needs validation!
+                       but= uiDefButS(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,cy,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
+                       uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
+                       cy -= 35;
                        
-                       /* for each coefficient, add to value, which we'll write to *cvalue in one go */
+                       /* draw controls for each coefficient and a + sign at end of row */
                        cp= data->coefficients;
                        for (i=0; (i < data->arraysize) && (cp); i++, cp++) {
-                       
+                               /* coefficient */
+                               uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 50, cy, 150, 20, cp, -FLT_MAX, FLT_MAX, 10, 3, "Coefficient for polynomial");
+                               
+                               /* 'x' param (and '+' if necessary) */
+                               if (i == 0)
+                                       strcpy(xval, "");
+                               else if (i == 1)
+                                       strcpy(xval, "x");
+                               else
+                                       sprintf(xval, "x^%d", i);
+                               uiDefBut(block, LABEL, 1, xval, 200, cy, 50, 20, NULL, 0.0, 0.0, 0, 0, "Power of x");
+                               
+                               if ( (i != (data->arraysize - 1)) || ((i==0) && data->arraysize==2) )
+                                       uiDefBut(block, LABEL, 1, "+", 300, cy, 30, 20, NULL, 0.0, 0.0, 0, 0, "Power of x");
+                               
+                               cy -= 20;
                        }
                }
                        break;
                
-#ifndef DISABLE_PYTHON
                case FCM_GENERATOR_EXPRESSION: /* py-expression */
                        // TODO...
                        break;
-#endif /* DISABLE_PYTHON */
        }
 }
 
@@ -286,10 +342,12 @@ static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fc
                uiBlockSetEmboss(block, UI_EMBOSSN);
                
                /* rounded header */
+#if 0 // XXX buggy...
                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), ""); 
+                       but= 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);
+#endif // XXX buggy
                
                /* 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");
@@ -303,6 +361,7 @@ static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fc
                /* 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);
        }
        
@@ -315,7 +374,8 @@ static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fc
                                break;
                        
                        default: /* unknown type */
-                               DRAW_BACKDROP(height, 96);
+                               height= 96;
+                               //DRAW_BACKDROP(height); // XXX buggy...
                                break;
                }
        }
@@ -330,11 +390,13 @@ static void graph_panel_modifiers(const bContext *C, ARegion *ar, short cntrl, b
        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);
        
+       uiNewPanelHeight(block, 204);
+       
        /* '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");
index 746424a10b9d47512e0a3d55ecd26837210d8ba6..44ff7e63673dacd58171338af8f77888359bc15c 100644 (file)
@@ -766,7 +766,7 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri
                }
                
                /* 2) draw handles and vertices as appropriate based on active */
-               if ((fcu->modifiers.first) && (fcm) && (fcm->type != FMODIFIER_TYPE_CYCLES)) {
+               if ( ((fcm) && (fcm->type != FMODIFIER_TYPE_CYCLES)) || (fcu->modifiers.first) ) {
                        // TODO: need to add code to show these... for cycles modifier, should fall through though...
                }
                else if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) { 
index 10ba28dbcac405b8f9c95d51685370c7e110d448..72e52f15a650ebfd72bb0a87cae8db2094380af6 100644 (file)
@@ -570,8 +570,8 @@ void ED_spacetype_ipo(void)
        art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
        art->regionid = RGN_TYPE_UI;
        art->minsizey= 200;
-       art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES;
-       art->listener= NULL; // graph_region_listener;
+       art->keymapflag= ED_KEYMAP_UI;
+       art->listener= graph_region_listener;
        art->init= graph_buttons_area_init;
        art->draw= graph_buttons_area_draw;