Blender V2.61 - r43446
|
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 /* ********************************************** */