Blender V2.61 - r43446

fmodifier_ui.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2009 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * 
00022  * Contributor(s): Blender Foundation, Joshua Leung
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00032 /* User-Interface Stuff for F-Modifiers:
00033  * This file defines the (C-Coded) templates + editing callbacks needed 
00034  * by the interface stuff or F-Modifiers, as used by F-Curves in the Graph Editor,
00035  * and NLA-Strips in the NLA Editor.
00036  *
00037  * Copy/Paste Buffer for F-Modifiers:
00038  * For now, this is also defined in this file so that it can be shared between the 
00039  */
00040  
00041 #include <string.h>
00042 
00043 #include "DNA_anim_types.h"
00044 #include "DNA_scene_types.h"
00045 
00046 #include "MEM_guardedalloc.h"
00047 
00048 #include "BLI_blenlib.h"
00049 #include "BLI_utildefines.h"
00050 
00051 #include "BKE_context.h"
00052 #include "BKE_fcurve.h"
00053 
00054 #include "WM_api.h"
00055 #include "WM_types.h"
00056 
00057 #include "RNA_access.h"
00058 
00059 #include "UI_interface.h"
00060 #include "UI_resources.h"
00061 
00062 #include "ED_anim_api.h"
00063 #include "ED_util.h"
00064 
00065 /* ********************************************** */
00066 /* UI STUFF */
00067 
00068 // XXX! --------------------------------
00069 /* temporary definition for limits of float number buttons (FLT_MAX tends to infinity with old system) */
00070 #define UI_FLT_MAX  10000.0f
00071 
00072 #define B_REDR                  1
00073 #define B_FMODIFIER_REDRAW      20
00074 
00075 /* macro for use here to draw background box and set height */
00076 // XXX for now, roundbox has it's callback func set to NULL to not intercept events
00077 #define DRAW_BACKDROP(height) \
00078     { \
00079         uiDefBut(block, ROUNDBOX, B_REDR, "", -3, yco-height, width+3, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \
00080     }
00081 
00082 /* callback to verify modifier data */
00083 static void validate_fmodifier_cb (bContext *UNUSED(C), void *fcm_v, void *UNUSED(arg))
00084 {
00085     FModifier *fcm= (FModifier *)fcm_v;
00086     FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
00087     
00088     /* call the verify callback on the modifier if applicable */
00089     if (fmi && fmi->verify_data)
00090         fmi->verify_data(fcm);
00091 }
00092 
00093 /* callback to remove the given modifier  */
00094 static void delete_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v)
00095 {
00096     ListBase *modifiers = (ListBase *)fmods_v;
00097     FModifier *fcm= (FModifier *)fcm_v;
00098     
00099     /* remove the given F-Modifier from the active modifier-stack */
00100     remove_fmodifier(modifiers, fcm);
00101 
00102     ED_undo_push(C, "Delete F-Curve Modifier");
00103     
00104     /* send notifiers */
00105     // XXX for now, this is the only way to get updates in all the right places... but would be nice to have a special one in this case 
00106     WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
00107 }
00108 
00109 /* --------------- */
00110     
00111 /* draw settings for generator modifier */
00112 static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, short width)
00113 {
00114     FMod_Generator *data= (FMod_Generator *)fcm->data;
00115     uiLayout /* *col, */ /* UNUSED */ *row;
00116     uiBlock *block;
00117     uiBut *but;
00118     PointerRNA ptr;
00119     
00120     /* init the RNA-pointer */
00121     RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
00122     
00123     /* basic settings (backdrop + mode selector + some padding) */
00124     /* col= uiLayoutColumn(layout, 1); */ /* UNUSED */
00125     block= uiLayoutGetBlock(layout);
00126     uiBlockBeginAlign(block);
00127         but= uiDefButR(block, MENU, B_FMODIFIER_REDRAW, NULL, 0, 0, width-30, UI_UNIT_Y, &ptr, "mode", -1, 0, 0, -1, -1, NULL);
00128         uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
00129         
00130         uiDefButR(block, TOG, B_FMODIFIER_REDRAW, NULL, 0, 0, width-30, UI_UNIT_Y, &ptr, "use_additive", -1, 0, 0, -1, -1, NULL);
00131     uiBlockEndAlign(block);
00132     
00133     /* now add settings for individual modes */
00134     switch (data->mode) {
00135         case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
00136         {
00137             float *cp = NULL;
00138             char xval[32];
00139             unsigned int i;
00140             
00141             /* draw polynomial order selector */
00142             row= uiLayoutRow(layout, 0);
00143             block= uiLayoutGetBlock(row);
00144                 but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 10,0,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
00145                 uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
00146             
00147             
00148             /* draw controls for each coefficient and a + sign at end of row */
00149             row= uiLayoutRow(layout, 1);
00150             block= uiLayoutGetBlock(row);
00151                 uiDefBut(block, LABEL, 1, "y = ", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
00152             
00153             cp= data->coefficients;
00154             for (i=0; (i < data->arraysize) && (cp); i++, cp++) {
00155                 /* coefficient */
00156                 uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 150, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient for polynomial");
00157                 
00158                 /* 'x' param (and '+' if necessary) */
00159                 if (i) {
00160                     if (i == 1)
00161                         strcpy(xval, "x");
00162                     else
00163                         sprintf(xval, "x^%u", i);
00164                     uiDefBut(block, LABEL, 1, xval, 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "Power of x");
00165                 }
00166                 
00167                 if ( (i != (data->arraysize - 1)) || ((i==0) && data->arraysize==2) ) {
00168                     uiDefBut(block, LABEL, 1, "+", 0,0 , 30, 20, NULL, 0.0, 0.0, 0, 0, "");
00169                     
00170                     /* next coefficient on a new row */
00171                     row= uiLayoutRow(layout, 1);
00172                     block= uiLayoutGetBlock(row);
00173                 }
00174             }
00175         }
00176             break;
00177         
00178         case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial expression */
00179         {
00180             float *cp = NULL;
00181             unsigned int i;
00182             
00183             /* draw polynomial order selector */
00184             row= uiLayoutRow(layout, 0);
00185             block= uiLayoutGetBlock(row);
00186                 but= uiDefButI(block, NUM, B_FMODIFIER_REDRAW, "Poly Order: ", 0,0,width-30,19, &data->poly_order, 1, 100, 0, 0, "'Order' of the Polynomial - for a polynomial with n terms, 'order' is n-1");
00187                 uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
00188             
00189             
00190             /* draw controls for each pair of coefficients */
00191             row= uiLayoutRow(layout, 1);
00192             block= uiLayoutGetBlock(row);
00193                 uiDefBut(block, LABEL, 1, "y=", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, "");
00194             
00195             cp= data->coefficients;
00196             for (i=0; (i < data->poly_order) && (cp); i++, cp+=2) {
00197                 /* opening bracket */
00198                 uiDefBut(block, LABEL, 1, "(", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, "");
00199                 
00200                 /* coefficients */
00201                 uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Coefficient of x");
00202                 
00203                 uiDefBut(block, LABEL, 1, "x+", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, "");
00204                 
00205                 uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp+1, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, "Second coefficient");
00206                 
00207                 /* closing bracket and '+' sign */
00208                 if ( (i != (data->poly_order - 1)) || ((i==0) && data->poly_order==2) ) {
00209                     uiDefBut(block, LABEL, 1, ") +", 0, 0, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
00210                     
00211                     /* set up new row for the next pair of coefficients*/
00212                     row= uiLayoutRow(layout, 1);
00213                     block= uiLayoutGetBlock(row);
00214                 }
00215                 else 
00216                     uiDefBut(block, LABEL, 1, ")", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, "");
00217             }
00218         }
00219             break;
00220     }
00221 }
00222 
00223 /* --------------- */
00224 
00225 /* draw settings for generator modifier */
00226 static void draw_modifier__fn_generator(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width))
00227 {
00228     uiLayout *col;
00229     PointerRNA ptr;
00230     
00231     /* init the RNA-pointer */
00232     RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr);
00233     
00234     /* add the settings */
00235     col= uiLayoutColumn(layout, 1);
00236         uiItemR(col, &ptr, "function_type", 0, "", ICON_NONE);
00237         uiItemR(col, &ptr, "use_additive", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
00238     
00239     col= uiLayoutColumn(layout, 0); // no grouping for now
00240         uiItemR(col, &ptr, "amplitude", 0, NULL, ICON_NONE);
00241         uiItemR(col, &ptr, "phase_multiplier", 0, NULL, ICON_NONE);
00242         uiItemR(col, &ptr, "phase_offset", 0, NULL, ICON_NONE);
00243         uiItemR(col, &ptr, "value_offset", 0, NULL, ICON_NONE);
00244 }
00245 
00246 /* --------------- */
00247 
00248 /* draw settings for cycles modifier */
00249 static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width))
00250 {
00251     uiLayout *split, *col;
00252     PointerRNA ptr;
00253     
00254     /* init the RNA-pointer */
00255     RNA_pointer_create(id, &RNA_FModifierCycles, fcm, &ptr);
00256     
00257     /* split into 2 columns 
00258      * NOTE: the mode comboboxes shouldn't get labels, otherwise there isn't enough room
00259      */
00260     split= uiLayoutSplit(layout, 0.5f, 0);
00261     
00262     /* before range */
00263     col= uiLayoutColumn(split, 1);
00264         uiItemL(col, "Before:", ICON_NONE);
00265         uiItemR(col, &ptr, "mode_before", 0, "", ICON_NONE);
00266         uiItemR(col, &ptr, "cycles_before", 0, NULL, ICON_NONE);
00267         
00268     /* after range */
00269     col= uiLayoutColumn(split, 1);
00270         uiItemL(col, "After:", ICON_NONE);
00271         uiItemR(col, &ptr, "mode_after", 0, "", ICON_NONE);
00272         uiItemR(col, &ptr, "cycles_after", 0, NULL, ICON_NONE);
00273 }
00274 
00275 /* --------------- */
00276 
00277 /* draw settings for noise modifier */
00278 static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width))
00279 {
00280     uiLayout *split, *col;
00281     PointerRNA ptr;
00282     
00283     /* init the RNA-pointer */
00284     RNA_pointer_create(id, &RNA_FModifierNoise, fcm, &ptr);
00285     
00286     /* blending mode */
00287     uiItemR(layout, &ptr, "blend_type", 0, NULL, ICON_NONE);
00288     
00289     /* split into 2 columns */
00290     split= uiLayoutSplit(layout, 0.5f, 0);
00291     
00292     /* col 1 */
00293     col= uiLayoutColumn(split, 0);
00294         uiItemR(col, &ptr, "scale", 0, NULL, ICON_NONE);
00295         uiItemR(col, &ptr, "strength", 0, NULL, ICON_NONE);
00296     
00297     /* col 2 */
00298     col= uiLayoutColumn(split, 0);
00299         uiItemR(col, &ptr, "phase", 0, NULL, ICON_NONE);
00300         uiItemR(col, &ptr, "depth", 0, NULL, ICON_NONE);
00301 }
00302 
00303 /* --------------- */
00304 
00305 #define BINARYSEARCH_FRAMEEQ_THRESH 0.0001f
00306 
00307 /* Binary search algorithm for finding where to insert Envelope Data Point.
00308  * Returns the index to insert at (data already at that index will be offset if replace is 0)
00309  */
00310 static int binarysearch_fcm_envelopedata_index (FCM_EnvelopeData array[], float frame, int arraylen, short *exists)
00311 {
00312     int start=0, end=arraylen;
00313     int loopbreaker= 0, maxloop= arraylen * 2;
00314     
00315     /* initialise exists-flag first */
00316     *exists= 0;
00317     
00318     /* sneaky optimisations (don't go through searching process if...):
00319      *  - keyframe to be added is to be added out of current bounds
00320      *  - keyframe to be added would replace one of the existing ones on bounds
00321      */
00322     if ((arraylen <= 0) || (array == NULL)) {
00323         printf("Warning: binarysearch_fcm_envelopedata_index() encountered invalid array \n");
00324         return 0;
00325     }
00326     else {
00327         /* check whether to add before/after/on */
00328         float framenum;
00329         
00330         /* 'First' Point (when only one point, this case is used) */
00331         framenum= array[0].time;
00332         if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
00333             *exists = 1;
00334             return 0;
00335         }
00336         else if (frame < framenum)
00337             return 0;
00338             
00339         /* 'Last' Point */
00340         framenum= array[(arraylen-1)].time;
00341         if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
00342             *exists= 1;
00343             return (arraylen - 1);
00344         }
00345         else if (frame > framenum)
00346             return arraylen;
00347     }
00348     
00349     
00350     /* most of the time, this loop is just to find where to put it
00351      *  - 'loopbreaker' is just here to prevent infinite loops 
00352      */
00353     for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
00354         /* compute and get midpoint */
00355         int mid = start + ((end - start) / 2);  /* we calculate the midpoint this way to avoid int overflows... */
00356         float midfra= array[mid].time;
00357         
00358         /* check if exactly equal to midpoint */
00359         if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) {
00360             *exists = 1;
00361             return mid;
00362         }
00363         
00364         /* repeat in upper/lower half */
00365         if (frame > midfra)
00366             start= mid + 1;
00367         else if (frame < midfra)
00368             end= mid - 1;
00369     }
00370     
00371     /* print error if loop-limit exceeded */
00372     if (loopbreaker == (maxloop-1)) {
00373         printf("Error: binarysearch_fcm_envelopedata_index() was taking too long \n");
00374         
00375         // include debug info 
00376         printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
00377     }
00378     
00379     /* not found, so return where to place it */
00380     return start;
00381 }
00382 
00383 /* callback to add new envelope data point */
00384 // TODO: should we have a separate file for things like this?
00385 static void fmod_envelope_addpoint_cb (bContext *C, void *fcm_dv, void *UNUSED(arg))
00386 {
00387     Scene *scene= CTX_data_scene(C);
00388     FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
00389     FCM_EnvelopeData *fedn;
00390     FCM_EnvelopeData fed;
00391     
00392     /* init template data */
00393     fed.min= -1.0f;
00394     fed.max= 1.0f;
00395     fed.time= (float)scene->r.cfra; // XXX make this int for ease of use?
00396     fed.f1= fed.f2= 0;
00397     
00398     /* check that no data exists for the current frame... */
00399     if (env->data) {
00400         short exists = -1;
00401         int i= binarysearch_fcm_envelopedata_index(env->data, (float)(scene->r.cfra), env->totvert, &exists);
00402         
00403         /* binarysearch_...() will set exists by default to 0, so if it is non-zero, that means that the point exists already */
00404         if (exists)
00405             return;
00406             
00407         /* add new */
00408         fedn= MEM_callocN((env->totvert+1)*sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
00409         
00410         /* add the points that should occur before the point to be pasted */
00411         if (i > 0)
00412             memcpy(fedn, env->data, i*sizeof(FCM_EnvelopeData));
00413         
00414         /* add point to paste at index i */
00415         *(fedn + i)= fed;
00416         
00417         /* add the points that occur after the point to be pasted */
00418         if (i < env->totvert) 
00419             memcpy(fedn+i+1, env->data+i, (env->totvert-i)*sizeof(FCM_EnvelopeData));
00420         
00421         /* replace (+ free) old with new */
00422         MEM_freeN(env->data);
00423         env->data= fedn;
00424         
00425         env->totvert++;
00426     }
00427     else {
00428         env->data= MEM_callocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
00429         *(env->data)= fed;
00430         
00431         env->totvert= 1;
00432     }
00433 }
00434 
00435 /* callback to remove envelope data point */
00436 // TODO: should we have a separate file for things like this?
00437 static void fmod_envelope_deletepoint_cb (bContext *UNUSED(C), void *fcm_dv, void *ind_v)
00438 {
00439     FMod_Envelope *env= (FMod_Envelope *)fcm_dv;
00440     FCM_EnvelopeData *fedn;
00441     int index= GET_INT_FROM_POINTER(ind_v);
00442     
00443     /* check that no data exists for the current frame... */
00444     if (env->totvert > 1) {
00445         /* allocate a new smaller array */
00446         fedn= MEM_callocN(sizeof(FCM_EnvelopeData)*(env->totvert-1), "FCM_EnvelopeData");
00447 
00448         memcpy(fedn, env->data, sizeof(FCM_EnvelopeData)*(index));
00449         memcpy(fedn + index, env->data + (index + 1), sizeof(FCM_EnvelopeData)*((env->totvert - index)-1));
00450         
00451         /* free old array, and set the new */
00452         MEM_freeN(env->data);
00453         env->data= fedn;
00454         env->totvert--;
00455     }
00456     else {
00457         /* just free array, since the only vert was deleted */
00458         if (env->data) {
00459             MEM_freeN(env->data);
00460             env->data= NULL;
00461         }
00462         env->totvert= 0;
00463     }
00464 }
00465 
00466 /* draw settings for envelope modifier */
00467 static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width))
00468 {
00469     FMod_Envelope *env= (FMod_Envelope *)fcm->data;
00470     FCM_EnvelopeData *fed;
00471     uiLayout *col, *row;
00472     uiBlock *block;
00473     uiBut *but;
00474     PointerRNA ptr;
00475     int i;
00476     
00477     /* init the RNA-pointer */
00478     RNA_pointer_create(id, &RNA_FModifierEnvelope, fcm, &ptr);
00479     
00480     /* general settings */
00481     col= uiLayoutColumn(layout, 1);
00482         uiItemL(col, "Envelope:", ICON_NONE);
00483         uiItemR(col, &ptr, "reference_value", 0, NULL, ICON_NONE);
00484         
00485         row= uiLayoutRow(col, 1);
00486             uiItemR(row, &ptr, "default_min", 0, "Min", ICON_NONE);
00487             uiItemR(row, &ptr, "default_max", 0, "Max", ICON_NONE);
00488             
00489     /* control points header */
00490     // TODO: move this control-point control stuff to using the new special widgets for lists
00491     // the current way is far too cramped
00492     row= uiLayoutRow(layout, 0);
00493     block= uiLayoutGetBlock(row);
00494         
00495         uiDefBut(block, LABEL, 1, "Control Points:", 0, 0, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
00496         
00497         but= uiDefBut(block, BUT, B_FMODIFIER_REDRAW, "Add Point", 0,0,150,19, NULL, 0, 0, 0, 0, "Adds a new control-point to the envelope on the current frame");
00498         uiButSetFunc(but, fmod_envelope_addpoint_cb, env, NULL);
00499         
00500     /* control points list */
00501     for (i=0, fed=env->data; i < env->totvert; i++, fed++) {
00502         /* get a new row to operate on */
00503         row= uiLayoutRow(layout, 1);
00504         block= uiLayoutGetBlock(row);
00505         
00506         uiBlockBeginAlign(block);
00507             but=uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Fra:", 0, 0, 90, 20, &fed->time, -MAXFRAMEF, MAXFRAMEF, 10, 1, "Frame that envelope point occurs");
00508             uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL);
00509             
00510             uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Min:", 0, 0, 100, 20, &fed->min, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Minimum bound of envelope at this point");
00511             uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "Max:", 0, 0, 100, 20, &fed->max, -UI_FLT_MAX, UI_FLT_MAX, 10, 2, "Maximum bound of envelope at this point");
00512             
00513             but= uiDefIconBut(block, BUT, B_FMODIFIER_REDRAW, ICON_X, 0, 0, 18, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Delete envelope control point");
00514             uiButSetFunc(but, fmod_envelope_deletepoint_cb, env, SET_INT_IN_POINTER(i));
00515         uiBlockBeginAlign(block);
00516     }
00517 }
00518 
00519 /* --------------- */
00520 
00521 /* draw settings for limits modifier */
00522 static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width))
00523 {
00524     uiLayout *split, *col /* , *row */ /* UNUSED */;
00525     PointerRNA ptr;
00526     
00527     /* init the RNA-pointer */
00528     RNA_pointer_create(id, &RNA_FModifierLimits, fcm, &ptr);
00529     
00530     /* row 1: minimum */
00531     {
00532         /* row= uiLayoutRow(layout, 0); */ /* UNUSED */
00533         
00534         /* split into 2 columns */
00535         split= uiLayoutSplit(layout, 0.5f, 0);
00536         
00537         /* x-minimum */
00538         col= uiLayoutColumn(split, 1);
00539             uiItemR(col, &ptr, "use_min_x", 0, NULL, ICON_NONE);
00540             uiItemR(col, &ptr, "min_x", 0, NULL, ICON_NONE);
00541             
00542         /* y-minimum*/
00543         col= uiLayoutColumn(split, 1);
00544             uiItemR(col, &ptr, "use_min_y", 0, NULL, ICON_NONE);
00545             uiItemR(col, &ptr, "min_y", 0, NULL, ICON_NONE);
00546     }
00547     
00548     /* row 2: maximum */
00549     {
00550         /* row= uiLayoutRow(layout, 0); */ /* UNUSED */
00551         
00552         /* split into 2 columns */
00553         split= uiLayoutSplit(layout, 0.5f, 0);
00554         
00555         /* x-minimum */
00556         col= uiLayoutColumn(split, 1);
00557             uiItemR(col, &ptr, "use_max_x", 0, NULL, ICON_NONE);
00558             uiItemR(col, &ptr, "max_x", 0, NULL, ICON_NONE);
00559             
00560         /* y-minimum*/
00561         col= uiLayoutColumn(split, 1);
00562             uiItemR(col, &ptr, "use_max_y", 0, NULL, ICON_NONE);
00563             uiItemR(col, &ptr, "max_y", 0, NULL, ICON_NONE);
00564     }
00565 }
00566 
00567 /* --------------- */
00568 
00569 /* draw settings for stepped interpolation modifier */
00570 static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, short UNUSED(width))
00571 {
00572     uiLayout *col, *sub;
00573     PointerRNA ptr;
00574     
00575     /* init the RNA-pointer */
00576     RNA_pointer_create(id, &RNA_FModifierStepped, fcm, &ptr);
00577     
00578     /* block 1: "stepping" settings */
00579     col= uiLayoutColumn(layout, 0);
00580         uiItemR(col, &ptr, "frame_step", 0, NULL, ICON_NONE);
00581         uiItemR(col, &ptr, "frame_offset", 0, NULL, ICON_NONE);
00582         
00583     /* block 2: start range settings */
00584     col= uiLayoutColumn(layout, 1);
00585         uiItemR(col, &ptr, "use_frame_start", 0, NULL, ICON_NONE);
00586         
00587         sub = uiLayoutColumn(col, 1);
00588         uiLayoutSetActive(sub, RNA_boolean_get(&ptr, "use_frame_start"));
00589             uiItemR(sub, &ptr, "frame_start", 0, NULL, ICON_NONE);
00590             
00591     /* block 3: end range settings */
00592     col= uiLayoutColumn(layout, 1);
00593         uiItemR(col, &ptr, "use_frame_end", 0, NULL, ICON_NONE);
00594         
00595         sub = uiLayoutColumn(col, 1);
00596         uiLayoutSetActive(sub, RNA_boolean_get(&ptr, "use_frame_end"));
00597             uiItemR(sub, &ptr, "frame_end", 0, NULL, ICON_NONE);
00598 }
00599 
00600 /* --------------- */
00601 
00602 void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm)
00603 {
00604     FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
00605     uiLayout *box, *row, *sub, *col;
00606     uiBlock *block;
00607     uiBut *but;
00608     short width= 314;
00609     PointerRNA ptr;
00610     
00611     /* init the RNA-pointer */
00612     RNA_pointer_create(id, &RNA_FModifier, fcm, &ptr);
00613     
00614     /* draw header */
00615     {
00616         /* get layout-row + UI-block for this */
00617         box= uiLayoutBox(layout);
00618         
00619         row= uiLayoutRow(box, 0);
00620         block= uiLayoutGetBlock(row); // err...
00621         
00622         /* left-align -------------------------------------------- */
00623         sub= uiLayoutRow(row, 1);
00624         uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
00625         
00626         uiBlockSetEmboss(block, UI_EMBOSSN);
00627         
00628         /* expand */
00629         uiItemR(sub, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
00630         
00631         /* checkbox for 'active' status (for now) */
00632         uiItemR(sub, &ptr, "active", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
00633         
00634         /* name */
00635         if (fmi)
00636             uiItemL(sub, fmi->name, ICON_NONE);
00637         else
00638             uiItemL(sub, "<Unknown Modifier>", ICON_NONE);
00639         
00640         /* right-align ------------------------------------------- */
00641         sub= uiLayoutRow(row, 1);
00642         uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
00643         
00644         
00645         /* 'mute' button */
00646         uiItemR(sub, &ptr, "mute", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
00647         
00648         uiBlockSetEmboss(block, UI_EMBOSSN);
00649         
00650         /* delete button */
00651         but= uiDefIconBut(block, BUT, B_REDR, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Delete F-Curve Modifier");
00652         uiButSetFunc(but, delete_fmodifier_cb, modifiers, fcm);
00653         
00654         uiBlockSetEmboss(block, UI_EMBOSS);
00655     }
00656     
00657     /* when modifier is expanded, draw settings */
00658     if (fcm->flag & FMODIFIER_FLAG_EXPANDED) {
00659         /* set up the flexible-box layout which acts as the backdrop for the modifier settings */
00660         box= uiLayoutBox(layout); 
00661         
00662         /* draw settings for individual modifiers */
00663         switch (fcm->type) {
00664             case FMODIFIER_TYPE_GENERATOR: /* Generator */
00665                 draw_modifier__generator(box, id, fcm, width);
00666                 break;
00667                 
00668             case FMODIFIER_TYPE_FN_GENERATOR: /* Built-In Function Generator */
00669                 draw_modifier__fn_generator(box, id, fcm, width);
00670                 break;
00671                 
00672             case FMODIFIER_TYPE_CYCLES: /* Cycles */
00673                 draw_modifier__cycles(box, id, fcm, width);
00674                 break;
00675                 
00676             case FMODIFIER_TYPE_ENVELOPE: /* Envelope */
00677                 draw_modifier__envelope(box, id, fcm, width);
00678                 break;
00679                 
00680             case FMODIFIER_TYPE_LIMITS: /* Limits */
00681                 draw_modifier__limits(box, id, fcm, width);
00682                 break;
00683             
00684             case FMODIFIER_TYPE_NOISE: /* Noise */
00685                 draw_modifier__noise(box, id, fcm, width);
00686                 break;
00687                 
00688             case FMODIFIER_TYPE_STEPPED: /* Stepped */
00689                 draw_modifier__stepped(box, id, fcm, width);
00690                 break;
00691             
00692             default: /* unknown type */
00693                 break;
00694         }
00695         
00696         /* one last panel below this: FModifier range */
00697         // TODO: experiment with placement of this
00698         {
00699             box = uiLayoutBox(layout);
00700             
00701             /* restricted range ----------------------------------------------------- */
00702             col = uiLayoutColumn(box, 1);
00703             
00704             /* top row: use restricted range */
00705             row= uiLayoutRow(col, 1);
00706             uiItemR(row, &ptr, "use_restricted_range", 0, NULL, ICON_NONE);
00707             
00708             if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) {
00709                 /* second row: settings */
00710                 row = uiLayoutRow(col, 1);
00711                 
00712                 uiItemR(row, &ptr, "frame_start", 0, "Start", ICON_NONE);
00713                 uiItemR(row, &ptr, "frame_end", 0, "End", ICON_NONE);
00714                 
00715                 /* third row: blending influence */
00716                 row = uiLayoutRow(col, 1);
00717                 
00718                 uiItemR(row, &ptr, "blend_in", 0, "In", ICON_NONE);
00719                 uiItemR(row, &ptr, "blend_out", 0, "Out", ICON_NONE);
00720             }
00721             
00722             /* influence -------------------------------------------------------------- */
00723             col = uiLayoutColumn(box, 1);
00724             
00725             /* top row: use influence */
00726             uiItemR(col, &ptr, "use_influence", 0, NULL, ICON_NONE);
00727             
00728             if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE) {
00729                 /* second row: influence value */
00730                 uiItemR(col, &ptr, "influence", 0, NULL, ICON_NONE);
00731             }
00732         }
00733     }
00734 }
00735 
00736 /* ********************************************** */
00737 /* COPY/PASTE BUFFER STUFF */
00738 
00739 /* Copy/Paste Buffer itself (list of FModifier 's) */
00740 static ListBase fmodifier_copypaste_buf = {NULL, NULL};
00741 
00742 /* ---------- */
00743 
00744 /* free the copy/paste buffer */
00745 void free_fmodifiers_copybuf (void)
00746 {
00747     /* just free the whole buffer */
00748     free_fmodifiers(&fmodifier_copypaste_buf);
00749 }
00750 
00751 /* copy the given F-Modifiers to the buffer, returning whether anything was copied or not
00752  * assuming that the buffer has been cleared already with free_fmodifiers_copybuf()
00753  *  - active: only copy the active modifier
00754  */
00755 short ANIM_fmodifiers_copy_to_buf (ListBase *modifiers, short active)
00756 {
00757     short ok = 1;
00758     
00759     /* sanity checks */
00760     if ELEM(NULL, modifiers, modifiers->first)
00761         return 0;
00762         
00763     /* copy the whole list, or just the active one? */
00764     if (active) {
00765         FModifier *fcm = find_active_fmodifier(modifiers);
00766         
00767         if (fcm) {
00768             FModifier *fcmN = copy_fmodifier(fcm);
00769             BLI_addtail(&fmodifier_copypaste_buf, fcmN);
00770         }
00771         else
00772             ok = 0;
00773     }
00774     else
00775         copy_fmodifiers(&fmodifier_copypaste_buf, modifiers);
00776         
00777     /* did we succeed? */
00778     return ok;
00779 }
00780 
00781 /* 'Paste' the F-Modifier(s) from the buffer to the specified list 
00782  *  - replace: free all the existing modifiers to leave only the pasted ones 
00783  */
00784 short ANIM_fmodifiers_paste_from_buf (ListBase *modifiers, short replace)
00785 {
00786     FModifier *fcm;
00787     short ok = 0;
00788     
00789     /* sanity checks */
00790     if (modifiers == NULL)
00791         return 0;
00792         
00793     /* if replacing the list, free the existing modifiers */
00794     if (replace)
00795         free_fmodifiers(modifiers);
00796         
00797     /* now copy over all the modifiers in the buffer to the end of the list */
00798     for (fcm= fmodifier_copypaste_buf.first; fcm; fcm= fcm->next) {
00799         /* make a copy of it */
00800         FModifier *fcmN = copy_fmodifier(fcm);
00801         
00802         /* make sure the new one isn't active, otherwise the list may get several actives */
00803         fcmN->flag &= ~FMODIFIER_FLAG_ACTIVE;
00804         
00805         /* now add it to the end of the list */
00806         BLI_addtail(modifiers, fcmN);
00807         ok = 1;
00808     }
00809     
00810     /* did we succeed? */
00811     return ok;
00812 }
00813 
00814 /* ********************************************** */