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, Joshua Leung 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): Joshua Leung (full recode) 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <stdio.h> 00034 #include <string.h> 00035 00036 #include "MEM_guardedalloc.h" 00037 00038 #include "BLI_blenlib.h" 00039 #include "BLI_utildefines.h" 00040 00041 #include "DNA_anim_types.h" 00042 #include "DNA_object_types.h" 00043 #include "DNA_material_types.h" 00044 #include "DNA_texture_types.h" 00045 #include "DNA_screen_types.h" 00046 #include "DNA_space_types.h" 00047 00048 #include "BKE_animsys.h" 00049 #include "BKE_depsgraph.h" 00050 #include "BKE_fcurve.h" 00051 #include "BKE_context.h" 00052 #include "BKE_report.h" 00053 #include "BKE_material.h" 00054 #include "BKE_texture.h" 00055 00056 #include "ED_keyframing.h" 00057 00058 #include "UI_interface.h" 00059 00060 #include "WM_api.h" 00061 #include "WM_types.h" 00062 00063 #include "RNA_access.h" 00064 #include "RNA_define.h" 00065 00066 #include "anim_intern.h" 00067 00068 /* called by WM */ 00069 void free_anim_drivers_copybuf (void); 00070 00071 /* ************************************************** */ 00072 /* Animation Data Validation */ 00073 00074 /* Get (or add relevant data to be able to do so) F-Curve from the driver stack, 00075 * for the given Animation Data block. This assumes that all the destinations are valid. 00076 * 00077 * - add: 0 - don't add anything if not found, 00078 * 1 - add new Driver FCurve, 00079 * -1 - add new Driver FCurve without driver stuff (for pasting) 00080 */ 00081 FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add) 00082 { 00083 AnimData *adt; 00084 FCurve *fcu; 00085 00086 /* sanity checks */ 00087 if ELEM(NULL, id, rna_path) 00088 return NULL; 00089 00090 /* init animdata if none available yet */ 00091 adt= BKE_animdata_from_id(id); 00092 if ((adt == NULL) && (add)) 00093 adt= BKE_id_add_animdata(id); 00094 if (adt == NULL) { 00095 /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ 00096 return NULL; 00097 } 00098 00099 /* try to find f-curve matching for this setting 00100 * - add if not found and allowed to add one 00101 * TODO: add auto-grouping support? how this works will need to be resolved 00102 */ 00103 fcu= list_find_fcurve(&adt->drivers, rna_path, array_index); 00104 00105 if ((fcu == NULL) && (add)) { 00106 /* use default settings to make a F-Curve */ 00107 fcu= MEM_callocN(sizeof(FCurve), "FCurve"); 00108 00109 fcu->flag = (FCURVE_VISIBLE|FCURVE_SELECTED); 00110 00111 /* store path - make copy, and store that */ 00112 fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path)); 00113 fcu->array_index= array_index; 00114 00115 /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */ 00116 if (add > 0) { 00117 /* add some new driver data */ 00118 fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); 00119 00120 /* add simple generator modifier for driver so that there is some visible representation */ 00121 add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); 00122 } 00123 00124 /* just add F-Curve to end of driver list */ 00125 BLI_addtail(&adt->drivers, fcu); 00126 } 00127 00128 /* return the F-Curve */ 00129 return fcu; 00130 } 00131 00132 /* ************************************************** */ 00133 /* Driver Management API */ 00134 00135 /* Main Driver Management API calls: 00136 * Add a new driver for the specified property on the given ID block 00137 */ 00138 short ANIM_add_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type) 00139 { 00140 PointerRNA id_ptr, ptr; 00141 PropertyRNA *prop; 00142 FCurve *fcu; 00143 int array_index_max; 00144 int done = 0; 00145 00146 /* validate pointer first - exit if failure */ 00147 RNA_id_pointer_create(id, &id_ptr); 00148 if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { 00149 BKE_reportf(reports, RPT_ERROR, 00150 "Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", 00151 id->name, rna_path); 00152 return 0; 00153 } 00154 00155 /* key entire array convenience method */ 00156 if (array_index == -1) { 00157 array_index_max= RNA_property_array_length(&ptr, prop); 00158 array_index= 0; 00159 } 00160 else 00161 array_index_max= array_index; 00162 00163 /* maximum index should be greater than the start index */ 00164 if (array_index == array_index_max) 00165 array_index_max += 1; 00166 00167 /* will only loop once unless the array index was -1 */ 00168 for (; array_index < array_index_max; array_index++) { 00169 /* create F-Curve with Driver */ 00170 fcu= verify_driver_fcurve(id, rna_path, array_index, 1); 00171 00172 if (fcu && fcu->driver) { 00173 ChannelDriver *driver= fcu->driver; 00174 00175 /* set the type of the driver */ 00176 driver->type= type; 00177 00178 /* creating drivers for buttons will create the driver(s) with type 00179 * "scripted expression" so that their values won't be lost immediately, 00180 * so here we copy those values over to the driver's expression 00181 */ 00182 if (type == DRIVER_TYPE_PYTHON) { 00183 PropertyType proptype= RNA_property_type(prop); 00184 int array= RNA_property_array_length(&ptr, prop); 00185 char *expression= driver->expression; 00186 int val, maxlen= sizeof(driver->expression); 00187 float fval; 00188 00189 if (proptype == PROP_BOOLEAN) { 00190 if (!array) val= RNA_property_boolean_get(&ptr, prop); 00191 else val= RNA_property_boolean_get_index(&ptr, prop, array_index); 00192 00193 BLI_strncpy(expression, (val)? "True": "False", maxlen); 00194 } 00195 else if (proptype == PROP_INT) { 00196 if (!array) val= RNA_property_int_get(&ptr, prop); 00197 else val= RNA_property_int_get_index(&ptr, prop, array_index); 00198 00199 BLI_snprintf(expression, maxlen, "%d", val); 00200 } 00201 else if (proptype == PROP_FLOAT) { 00202 if (!array) fval= RNA_property_float_get(&ptr, prop); 00203 else fval= RNA_property_float_get_index(&ptr, prop, array_index); 00204 00205 BLI_snprintf(expression, maxlen, "%.3f", fval); 00206 } 00207 } 00208 00209 /* for easier setup of drivers from UI, a driver variable should be 00210 * added if flag is set (UI calls only) 00211 */ 00212 if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) { 00213 /* assume that users will mostly want this to be of type "Transform Channel" too, 00214 * since this allows the easiest setting up of common rig components 00215 */ 00216 DriverVar *dvar = driver_add_new_variable(driver); 00217 driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN); 00218 } 00219 } 00220 00221 /* set the done status */ 00222 done += (fcu != NULL); 00223 } 00224 00225 /* done */ 00226 return done; 00227 } 00228 00229 /* Main Driver Management API calls: 00230 * Remove the driver for the specified property on the given ID block (if available) 00231 */ 00232 short ANIM_remove_driver (ReportList *UNUSED(reports), ID *id, const char rna_path[], int array_index, short UNUSED(flag)) 00233 { 00234 AnimData *adt; 00235 FCurve *fcu; 00236 int success= 0; 00237 00238 /* we don't check the validity of the path here yet, but it should be ok... */ 00239 adt= BKE_animdata_from_id(id); 00240 00241 if (adt) { 00242 if (array_index == -1) { 00243 /* step through all drivers, removing all of those with the same base path */ 00244 FCurve *fcu_iter= adt->drivers.first; 00245 00246 while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) { 00247 /* store the next fcurve for looping */ 00248 fcu_iter= fcu->next; 00249 00250 /* remove F-Curve from driver stack, then free it */ 00251 BLI_remlink(&adt->drivers, fcu); 00252 free_fcurve(fcu); 00253 00254 /* done successfully */ 00255 success |= 1; 00256 } 00257 } 00258 else { 00259 /* find the matching driver and remove it only 00260 * Note: here is one of the places where we don't want new F-Curve + Driver added! 00261 * so 'add' var must be 0 00262 */ 00263 fcu= verify_driver_fcurve(id, rna_path, array_index, 0); 00264 if (fcu) { 00265 BLI_remlink(&adt->drivers, fcu); 00266 free_fcurve(fcu); 00267 00268 success = 1; 00269 } 00270 } 00271 } 00272 00273 return success; 00274 } 00275 00276 /* ************************************************** */ 00277 /* Driver Management API - Copy/Paste Drivers */ 00278 00279 /* Copy/Paste Buffer for Driver Data... */ 00280 static FCurve *channeldriver_copypaste_buf = NULL; 00281 00282 /* This function frees any MEM_calloc'ed copy/paste buffer data */ 00283 // XXX find some header to put this in! 00284 void free_anim_drivers_copybuf (void) 00285 { 00286 /* free the buffer F-Curve if it exists, as if it were just another F-Curve */ 00287 if (channeldriver_copypaste_buf) 00288 free_fcurve(channeldriver_copypaste_buf); 00289 channeldriver_copypaste_buf= NULL; 00290 } 00291 00292 /* Checks if there is a driver in the copy/paste buffer */ 00293 short ANIM_driver_can_paste (void) 00294 { 00295 return (channeldriver_copypaste_buf != NULL); 00296 } 00297 00298 /* ------------------- */ 00299 00300 /* Main Driver Management API calls: 00301 * Make a copy of the driver for the specified property on the given ID block 00302 */ 00303 short ANIM_copy_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag)) 00304 { 00305 PointerRNA id_ptr, ptr; 00306 PropertyRNA *prop; 00307 FCurve *fcu; 00308 00309 /* validate pointer first - exit if failure */ 00310 RNA_id_pointer_create(id, &id_ptr); 00311 if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { 00312 BKE_reportf(reports, RPT_ERROR, 00313 "Could not find Driver to copy, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", 00314 id->name, rna_path); 00315 return 0; 00316 } 00317 00318 /* try to get F-Curve with Driver */ 00319 fcu= verify_driver_fcurve(id, rna_path, array_index, 0); 00320 00321 /* clear copy/paste buffer first (for consistency with other copy/paste buffers) */ 00322 free_anim_drivers_copybuf(); 00323 00324 /* copy this to the copy/paste buf if it exists */ 00325 if (fcu && fcu->driver) { 00326 /* make copies of some info such as the rna_path, then clear this info from the F-Curve temporarily 00327 * so that we don't end up wasting memory storing the path which won't get used ever... 00328 */ 00329 char *tmp_path = fcu->rna_path; 00330 fcu->rna_path= NULL; 00331 00332 /* make a copy of the F-Curve with */ 00333 channeldriver_copypaste_buf= copy_fcurve(fcu); 00334 00335 /* restore the path */ 00336 fcu->rna_path= tmp_path; 00337 00338 /* copied... */ 00339 return 1; 00340 } 00341 00342 /* done */ 00343 return 0; 00344 } 00345 00346 /* Main Driver Management API calls: 00347 * Add a new driver for the specified property on the given ID block or replace an existing one 00348 * with the driver + driver-curve data from the buffer 00349 */ 00350 short ANIM_paste_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag)) 00351 { 00352 PointerRNA id_ptr, ptr; 00353 PropertyRNA *prop; 00354 FCurve *fcu; 00355 00356 /* validate pointer first - exit if failure */ 00357 RNA_id_pointer_create(id, &id_ptr); 00358 if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { 00359 BKE_reportf(reports, RPT_ERROR, 00360 "Could not paste Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", 00361 id->name, rna_path); 00362 return 0; 00363 } 00364 00365 /* if the buffer is empty, cannot paste... */ 00366 if (channeldriver_copypaste_buf == NULL) { 00367 BKE_report(reports, RPT_ERROR, "Paste Driver: No Driver to paste"); 00368 return 0; 00369 } 00370 00371 /* create Driver F-Curve, but without data which will be copied across... */ 00372 fcu= verify_driver_fcurve(id, rna_path, array_index, -1); 00373 00374 if (fcu) { 00375 /* copy across the curve data from the buffer curve 00376 * NOTE: this step needs care to not miss new settings 00377 */ 00378 /* keyframes/samples */ 00379 fcu->bezt= MEM_dupallocN(channeldriver_copypaste_buf->bezt); 00380 fcu->fpt= MEM_dupallocN(channeldriver_copypaste_buf->fpt); 00381 fcu->totvert= channeldriver_copypaste_buf->totvert; 00382 00383 /* modifiers */ 00384 copy_fmodifiers(&fcu->modifiers, &channeldriver_copypaste_buf->modifiers); 00385 00386 /* extrapolation mode */ 00387 fcu->extend= channeldriver_copypaste_buf->extend; 00388 00389 /* the 'juicy' stuff - the driver */ 00390 fcu->driver= fcurve_copy_driver(channeldriver_copypaste_buf->driver); 00391 } 00392 00393 /* done */ 00394 return (fcu != NULL); 00395 } 00396 00397 /* ************************************************** */ 00398 /* UI-Button Interface */ 00399 00400 /* Temporary wrapper for driver operators for buttons to make it easier to create 00401 * such drivers by rerouting all paths through the active object instead so that 00402 * they will get picked up by the dependency system. 00403 * 00404 * < C: context pointer - for getting active data 00405 * <> ptr: RNA pointer for property's datablock. May be modified as result of path remapping. 00406 * < prop: RNA definition of property to add for 00407 * 00408 * > returns: MEM_alloc'd string representing the path to the property from the given PointerRNA 00409 */ 00410 static char *get_driver_path_hack (bContext *C, PointerRNA *ptr, PropertyRNA *prop) 00411 { 00412 ID *id = (ID *)ptr->id.data; 00413 ScrArea *sa = CTX_wm_area(C); 00414 00415 /* get standard path which may be extended */ 00416 char *basepath = RNA_path_from_ID_to_property(ptr, prop); 00417 char *path = basepath; /* in case no remapping is needed */ 00418 00419 /* Remapping will only be performed in the Properties Editor, as only this 00420 * restricts the subspace of options to the 'active' data (a manageable state) 00421 */ 00422 // TODO: watch out for pinned context? 00423 if ((sa) && (sa->spacetype == SPACE_BUTS)) { 00424 Object *ob = CTX_data_active_object(C); 00425 00426 if (ob && id) { 00427 /* only id-types which can be remapped to go through objects should be considered */ 00428 switch (GS(id->name)) { 00429 case ID_MA: /* materials */ 00430 { 00431 Material *ma = give_current_material(ob, ob->actcol); 00432 00433 /* assumes: material will only be shown if it is active objects's active material it's ok */ 00434 if ((ID*)ma == id) { 00435 /* create new path */ 00436 // TODO: use RNA path functions to construct instead? 00437 path = BLI_sprintfN("material_slots[\"%s\"].material.%s", 00438 ma->id.name+2, basepath); 00439 00440 /* free old one */ 00441 MEM_freeN(basepath); 00442 } 00443 } 00444 break; 00445 00446 case ID_TE: /* textures */ 00447 { 00448 Material *ma = give_current_material(ob, ob->actcol); 00449 Tex *tex = give_current_material_texture(ma); 00450 00451 /* assumes: texture will only be shown if it is active material's active texture it's ok */ 00452 if ((ID*)tex == id) { 00453 /* create new path */ 00454 // TODO: use RNA path functions to construct step by step instead? 00455 path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s", 00456 ma->id.name+2, tex->id.name+2, basepath); 00457 00458 /* free old one */ 00459 MEM_freeN(basepath); 00460 } 00461 } 00462 break; 00463 } 00464 00465 /* fix RNA pointer, as we've now changed the ID root by changing the paths */ 00466 if (basepath != path) { 00467 /* rebase provided pointer so that it starts from object... */ 00468 RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr); 00469 } 00470 } 00471 } 00472 00473 /* the path should now have been corrected for use */ 00474 return path; 00475 } 00476 00477 /* Add Driver Button Operator ------------------------ */ 00478 00479 static int add_driver_button_exec (bContext *C, wmOperator *op) 00480 { 00481 PointerRNA ptr= {{NULL}}; 00482 PropertyRNA *prop= NULL; 00483 short success= 0; 00484 int index, all= RNA_boolean_get(op->ptr, "all"); 00485 00486 /* try to create driver using property retrieved from UI */ 00487 uiContextActiveProperty(C, &ptr, &prop, &index); 00488 00489 if (all) 00490 index= -1; 00491 00492 if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { 00493 char *path= get_driver_path_hack(C, &ptr, prop); 00494 short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; 00495 00496 if (path) { 00497 success+= ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON); 00498 00499 MEM_freeN(path); 00500 } 00501 } 00502 00503 if (success) { 00504 /* send updates */ 00505 uiContextAnimUpdate(C); 00506 00507 DAG_ids_flush_update(CTX_data_main(C), 0); 00508 00509 WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX 00510 } 00511 00512 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; 00513 } 00514 00515 void ANIM_OT_driver_button_add (wmOperatorType *ot) 00516 { 00517 /* identifiers */ 00518 ot->name= "Add Driver"; 00519 ot->idname= "ANIM_OT_driver_button_add"; 00520 ot->description= "Add driver(s) for the property(s) connected represented by the highlighted button"; 00521 00522 /* callbacks */ 00523 ot->exec= add_driver_button_exec; 00524 //op->poll= ??? // TODO: need to have some animateable property to do this 00525 00526 /* flags */ 00527 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00528 00529 /* properties */ 00530 RNA_def_boolean(ot->srna, "all", 1, "All", "Create drivers for all elements of the array"); 00531 } 00532 00533 /* Remove Driver Button Operator ------------------------ */ 00534 00535 static int remove_driver_button_exec (bContext *C, wmOperator *op) 00536 { 00537 PointerRNA ptr= {{NULL}}; 00538 PropertyRNA *prop= NULL; 00539 short success= 0; 00540 int index, all= RNA_boolean_get(op->ptr, "all"); 00541 00542 /* try to find driver using property retrieved from UI */ 00543 uiContextActiveProperty(C, &ptr, &prop, &index); 00544 00545 if (all) 00546 index= -1; 00547 00548 if (ptr.id.data && ptr.data && prop) { 00549 char *path= get_driver_path_hack(C, &ptr, prop); 00550 00551 success= ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0); 00552 MEM_freeN(path); 00553 } 00554 00555 if (success) { 00556 /* send updates */ 00557 uiContextAnimUpdate(C); 00558 00559 DAG_ids_flush_update(CTX_data_main(C), 0); 00560 00561 WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX 00562 } 00563 00564 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; 00565 } 00566 00567 void ANIM_OT_driver_button_remove (wmOperatorType *ot) 00568 { 00569 /* identifiers */ 00570 ot->name= "Remove Driver"; 00571 ot->idname= "ANIM_OT_driver_button_remove"; 00572 ot->description= "Remove the driver(s) for the property(s) connected represented by the highlighted button"; 00573 00574 /* callbacks */ 00575 ot->exec= remove_driver_button_exec; 00576 //op->poll= ??? // TODO: need to have some driver to be able to do this... 00577 00578 /* flags */ 00579 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00580 00581 /* properties */ 00582 RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array"); 00583 } 00584 00585 /* Copy Driver Button Operator ------------------------ */ 00586 00587 static int copy_driver_button_exec (bContext *C, wmOperator *op) 00588 { 00589 PointerRNA ptr= {{NULL}}; 00590 PropertyRNA *prop= NULL; 00591 short success= 0; 00592 int index; 00593 00594 /* try to create driver using property retrieved from UI */ 00595 uiContextActiveProperty(C, &ptr, &prop, &index); 00596 00597 if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { 00598 char *path= get_driver_path_hack(C, &ptr, prop); 00599 00600 if (path) { 00601 /* only copy the driver for the button that this was involved for */ 00602 success= ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0); 00603 00604 uiContextAnimUpdate(C); 00605 00606 MEM_freeN(path); 00607 } 00608 } 00609 00610 /* since we're just copying, we don't really need to do anything else...*/ 00611 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; 00612 } 00613 00614 void ANIM_OT_copy_driver_button (wmOperatorType *ot) 00615 { 00616 /* identifiers */ 00617 ot->name= "Copy Driver"; 00618 ot->idname= "ANIM_OT_copy_driver_button"; 00619 ot->description= "Copy the driver for the highlighted button"; 00620 00621 /* callbacks */ 00622 ot->exec= copy_driver_button_exec; 00623 //op->poll= ??? // TODO: need to have some driver to be able to do this... 00624 00625 /* flags */ 00626 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00627 } 00628 00629 /* Paste Driver Button Operator ------------------------ */ 00630 00631 static int paste_driver_button_exec (bContext *C, wmOperator *op) 00632 { 00633 PointerRNA ptr= {{NULL}}; 00634 PropertyRNA *prop= NULL; 00635 short success= 0; 00636 int index; 00637 00638 /* try to create driver using property retrieved from UI */ 00639 uiContextActiveProperty(C, &ptr, &prop, &index); 00640 00641 if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { 00642 char *path= get_driver_path_hack(C, &ptr, prop); 00643 00644 if (path) { 00645 /* only copy the driver for the button that this was involved for */ 00646 success= ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0); 00647 00648 uiContextAnimUpdate(C); 00649 00650 MEM_freeN(path); 00651 } 00652 } 00653 00654 /* since we're just copying, we don't really need to do anything else...*/ 00655 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; 00656 } 00657 00658 void ANIM_OT_paste_driver_button (wmOperatorType *ot) 00659 { 00660 /* identifiers */ 00661 ot->name= "Paste Driver"; 00662 ot->idname= "ANIM_OT_paste_driver_button"; 00663 ot->description= "Paste the driver in the copy/paste buffer for the highlighted button"; 00664 00665 /* callbacks */ 00666 ot->exec= paste_driver_button_exec; 00667 //op->poll= ??? // TODO: need to have some driver to be able to do this... 00668 00669 /* flags */ 00670 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00671 } 00672 00673 /* ************************************************** */