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